FreeCalypso > hg > freecalypso-sw
view gsm-fw/ccd/cdc_com.c @ 982:461f7ee5f254
fc-olddump: brown paper bag
author | Mychaela Falconia <falcon@ivan.Harhan.ORG> |
---|---|
date | Thu, 10 Dec 2015 05:35:42 +0000 |
parents | 970d6199f2c5 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : cdc_com.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 | Definitions of common functions for encoding and decoding of | GSM, GPRS or UMTS air interface messages +----------------------------------------------------------------------------- */ #ifdef _MSDOS #include <dos.h> #include <conio.h> #endif /* * standard definitions like UCHAR, ERROR etc. */ #include "typedefs.h" #include "header.h" #include <string.h> #include <stdlib.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" /* * Declaration of coder/decoder-tables */ #include "ccdtable.h" #include "ccddata.h" /* * Prototypes and constants in the common part of ccd */ #include "ccd.h" #include "ccd_codingtypes.h" /* * Need memory allocation functions for dynamic arrays (pointers) */ #ifdef DYNAMIC_ARRAYS #include "vsi.h" #endif #ifndef RUN_FLASH const UBYTE padding_bits[8] = {0, 0, 1, 0, 1, 0, 1, 1}; const UBYTE padding_bits_prev[8] = {1, 0, 0, 1, 0, 1, 0, 1}; #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* Attention for RUN_...: static data (used in cdc_skipElem) */ static UBYTE dummy[256]; #endif /* !RUN_FLASH */ typedef struct unknownTag { U8 errCode; U8 tag; U16 bitpos; struct unknownTag *next; }T_UNKNOWN_TAG; #ifndef RUN_FLASH /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_init_ctx_table | +--------------------------------------------------------------------+ PURPOSE : init the iei_ctx table. This must be done before decoding a message. */ static void cdc_init_ctx_table (T_CCD_Globs *globs) { int i; #ifdef DEBUG_CCD TRACE_CCD (globs, "CONTEXT table init"); #endif for (i=0; i<MAX_RECURSIONS_PER_MSG; i++) { globs->iei_ctx[i].valid = FALSE; } globs->numEOCPending = 0; } #endif /* !RUN_FLASH */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCD | | STATE : code ROUTINE : cdc_BCD_decode | +--------------------------------------------------------------------+ PURPOSE : Decoding of an bitstream containing a BCD string with k digits. If the first digit in the bitstream is DIGIT_2, the digits are ordered in the Bitstream as follow: MSBit LSBit 8 7 6 5 4 3 2 1 DIGIT_2 DIGIT_1 Octett n DIGIT_4 DIGIT_3 Octett n+1 : : : : : : : : DIGIT_Z DIGIT_X Octett n+m if the number of the digits is odd, the last Octett contains the bit pattern 1111 in the most significant nibble. : : : : : : : : 1 1 1 1 DIGIT_X Octett n+m NOTE: If the first digit in the bitstream is DIGIT_1, the digits are ordered in a different way: MSBit LSBit 8 7 6 5 4 3 2 1 DIGIT_1 XXXXXXX Octett n DIGIT_3 DIGIT_2 Octett n+1 DIGIT_5 DIGIT_4 Octett n+2 : : : : : : : : DIGIT_Z DIGIT_X Octett n+m In this case, if the number of the digits is even, the last octett contains the bit pattern 1111 in the most significant nibble. : : : : : : : : 1 1 1 1 DIGIT_X Octett n+m The amount of digits may be constant or variable. NOTE: A special case (type BCD_NOFILL) is the encoding and decoding of a BCD string starting with DIGIT_2 but without setting/checking the most significant nibble of Octet n+m. This nibble belongs to the next IE (usual coded by type BCD_MNC). Type BCD_NOFILL is coded by startDigit EQ 2. */ void cdc_BCD_decode (const ULONG e_ref, UBYTE startDigit, T_CCD_Globs *globs) { BOOL is_variable; UBYTE *digits; UBYTE *addr_c_xxx; ULONG i, max_rep, nibbles_to_read, repeat; ULONG cix_ref, num_prolog_steps, prolog_step_ref; int k; #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "cdc_BCD_decode()"); #else TRACE_CCD (globs, "cdc_BCD_decode() %s", ccddata_get_alias((USHORT) e_ref, 1)); #endif #endif cix_ref = melem[e_ref].calcIdxRef; num_prolog_steps = calcidx[cix_ref].numPrologSteps; prolog_step_ref = calcidx[cix_ref].prologStepRef; /* * if this element is conditional, check the condition */ if (calcidx[cix_ref].numCondCalcs NEQ 0 AND ! ccd_conditionOK (e_ref, globs)) return; /* * if this element have a defined Prolog * we have to process it before decoding the bitstream */ if (num_prolog_steps) { ccd_performOperations (num_prolog_steps, prolog_step_ref, globs); } /* * if this element is repeatable, and the number of * repeats depends on another element, calculate the repeater */ if (melem[e_ref].repType NEQ ' ') { is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs); } else { repeat = 1; is_variable = FALSE; } /* * setup the offset into the C-structure for this element */ globs->pstructOffs = melem[e_ref].structOffs; if (melem[e_ref].optional) { /* * for optional elements set the valid-flag */ globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE; } if (is_variable) { /* * for variable sized elements store the min-value * as counter into the C-Structure (c_xxx). */ addr_c_xxx = (UBYTE *) (globs->pstruct + globs->pstructOffs++); if (max_rep > 255) globs->pstructOffs++; } else addr_c_xxx = NULL; digits = (UBYTE *) (globs->pstruct + globs->pstructOffs); if (startDigit EQ 1) { /* * read the BCD digits out of the bitstream. * The read order is 1,X,3,2,5,4 ... */ /* * if the first digit is digit_1 read it and skip * the next 4 bits, because they do not belong to * the BCD stream. */ digits[0] = bf_decodeByteNumber (4, globs); bf_incBitpos (4, globs); /* * make a correction on the repeatvalue */ if (melem[e_ref].repType NEQ ' ') { is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs); } k = 2; for (i=0; i<repeat; i++) { digits[k] = bf_decodeByteNumber (4, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "BCD digit (%X) read", (USHORT) digits[k]); #endif k = ((k&1) EQ 0) ? (k-1) : (k+3); } } else { /* * read the BCD digits out of the bitstream. * The read order is 2,1,4,3,6,5 ... */ k = 1; nibbles_to_read = repeat; if (repeat & 1) nibbles_to_read++; for (i=0; i<nibbles_to_read; i++) { digits[k] = bf_decodeByteNumber (4, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "BCD digit (%X) read", (USHORT) digits[k]); #endif k = ((k&1) EQ 1) ? (k-1) : (k+3); } } /* * check the 1111 pattern and the even odd criteria */ if (startDigit EQ 1) { if ((repeat & 1) EQ 0) { /* even number of digits */ if (digits[repeat] NEQ 0xf) repeat++; } } else { if ((repeat & 1) EQ 1) { /* odd number of digits */ if (digits[repeat] NEQ 0xf AND startDigit EQ 0) { /* * if there is no 1111 pattern generate an error */ ccd_setError (globs, ERR_PATTERN_MISMATCH, CONTINUE, (USHORT) (globs->bitpos-8), (USHORT) -1); } } else { /* even number of digits - the last may be 0xf */ if (digits[repeat-1] EQ 0xf) repeat--; /* 0x0f dosn't belong to the coded digit string */ } } if (addr_c_xxx NEQ NULL) { /* * store the number of digits into the * c_xxx variable if there is one. */ if (max_rep > 65535) { ULONG *addr_c_xxx_u32; addr_c_xxx_u32 = (ULONG *)addr_c_xxx; *addr_c_xxx_u32 = repeat; } else if (max_rep > 255) { USHORT *addr_c_xxx_u16; addr_c_xxx_u16 = (USHORT *)addr_c_xxx; *addr_c_xxx_u16 = (USHORT) repeat; } else *addr_c_xxx = (UBYTE) repeat; } } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCD | | STATE : code ROUTINE : cdc_BCD_encode | +--------------------------------------------------------------------+ PURPOSE : encoding a Bytearray, that contain a BCD Number, into bitstream. The digits coded in the following order into the Bitstream: MSBit LSBit 7 8 6 5 4 3 2 1 DIGIT_2 DIGIT_1 Octett n DIGIT_4 DIGIT_3 Octett n+1 : : : : : : : : DIGIT_Z DIGIT_X Octett n+m if the number of the digits are odd, the bit pattern 1111 will be coded in the most significant nibble of the last Octett. : : : : : : : : 1 1 1 1 DIGIT_X Octett n+m The amount of digits may be constant or variable. */ void cdc_BCD_encode (const ULONG e_ref, UBYTE startDigit, T_CCD_Globs *globs) { ULONG repeat; int k; register UBYTE *digits; BOOL fullBitsNeeded=FALSE; ULONG cix_ref, num_prolog_steps, prolog_step_ref; #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "cdc_BCD_encode()"); #else TRACE_CCD (globs, "cdc_BCD_encode() %s", ccddata_get_alias((USHORT) e_ref, 1)); #endif #endif cix_ref = melem[e_ref].calcIdxRef; num_prolog_steps = calcidx[cix_ref].numPrologSteps; prolog_step_ref = calcidx[cix_ref].prologStepRef; /* * if this element is conditional, check the condition */ if (calcidx[cix_ref].numCondCalcs NEQ 0 AND ! ccd_conditionOK (e_ref, globs)) return; /* * if this element have a defined Prolog * we have to process it before decoding the bitstream */ if (num_prolog_steps) { ccd_performOperations (num_prolog_steps, prolog_step_ref, globs); } /* * setup the offset into the C-structure for this element */ globs->pstructOffs = melem[e_ref].structOffs; if (melem[e_ref].optional) { /* * for optional elements check the valid-flag */ if (globs->pstruct[globs->pstructOffs++] == FALSE) return; #ifdef DEBUG_CCD else if (globs->pstruct [melem[e_ref].structOffs] != TRUE) { TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d", e_ref); } #endif } /* * if this element is repeatable, and the number of * repeats depends on another element, calculate the repeater */ if (melem[e_ref].repType EQ 'v' OR melem[e_ref].repType EQ 'i') { /* * for variable sized elements read the amount * of repeats out of the C-Structure (c_xxx). * If the number of repeats given by the C-Structure * exceeds the allowed value (maxRepeat) CCD gives a warning! */ if (melem[e_ref].maxRepeat > 255) { ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++)); repeat = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat); if (repeat < count) ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, e_ref, globs->pstruct + globs->pstructOffs); } else { repeat = (ULONG)MINIMUM (globs->pstruct[globs->pstructOffs], melem[e_ref].maxRepeat); if ( repeat < (ULONG) (globs->pstruct[globs->pstructOffs]) ) ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } globs->pstructOffs++; } else if (melem[e_ref].repType EQ 'c') repeat = (ULONG) melem[e_ref].maxRepeat; else repeat = 1; /* There seems to exist cases where address contains no digits. */ if (repeat EQ 0) return; /* * setup the read pointer to the byte array that contain * the BCD number. */ digits = (UBYTE *) (globs->pstruct + globs->pstructOffs); if (startDigit EQ 1) { /* * write the BCD digits into the bitstream. * The write order is 1,X,3,2,5,4 ... */ if ((repeat & 1) EQ 0) { /* * for even digits store the 1111 pattern at last digit */ fullBitsNeeded = TRUE; } /* * if the first digit is digit_1 write it and skip * the next 4 bits, because they does not belong to * the BCD stream. */ bf_codeByteNumber (4, digits[0], globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "BCD digit (%X) written", (USHORT) digits[0]); TRACE_CCD (globs, "skipping 4 bits"); #endif bf_incBitpos (4, globs); k = 2; while (--repeat>1) { bf_codeByteNumber (4, digits[k], globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "BCD digit (%X) written", (USHORT) digits[k]); #endif k = ((k&1) EQ 0) ? (k-1) : (k+3); } if (repeat) { if (fullBitsNeeded) { bf_codeByteNumber (4, 0xf, globs); k = ((k&1) EQ 0) ? (k-1) : (k+3); } bf_codeByteNumber (4, digits[k], globs); } } else { /* * store the BCD digits into the bitstream. * The write order is 2,1,4,3,6,5 ... */ if (repeat & 1) { /* * for odd digits store the 1111 pattern at last digit * in case of type BCD_NOFILL use 0 instead */ fullBitsNeeded = TRUE; } k = 1; while ( repeat-- > 1) { bf_codeByteNumber (4, digits[k], globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "BCD digit (%X) written", (USHORT) digits[k]); #endif k = ((k&1) EQ 1) ? (k-1) : (k+3); } if (fullBitsNeeded) { bf_codeByteNumber (4, (UBYTE)((startDigit NEQ 2) ? 0xf : 0), globs); k = ((k&1) EQ 1) ? (k-1) : (k+3); } bf_codeByteNumber (4, digits[k], globs); } } #endif /* !RUN_INT_RAM */ #ifndef RUN_FLASH /* Attention for RUN_...: static function */ /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_init_table | +--------------------------------------------------------------------+ PURPOSE : init the iei_table for each new msg that is to be decoded. The c_ref references a composition (msg). The function initialises the table entrys only for the used iei for this message. */ static void cdc_init_table (const ULONG c_ref, T_CCD_Globs *globs) { ULONG look_up; ULONG num_elems; ULONG ie_table_idx; ULONG rlevel = globs->ccd_recurs_level; if (globs->iei_ctx[rlevel].valid AND rlevel < (ULONG) globs->last_level) { int i; /* * this iei context has been initialized before, so * no action for this. All deeper levels must be set * to invalid; */ for (i=globs->last_level; i<MAX_RECURSIONS_PER_MSG; i++) globs->iei_ctx[i].valid = FALSE; #ifdef DEBUG_CCD TRACE_CCD (globs, "TAG table init for old level %d", rlevel); #endif } else { /* * this iei context has not been initialized before, so * initialize the iei_table for this. */ #ifdef DEBUG_CCD TRACE_CCD (globs, "TAG table init for new level %d", rlevel); #endif look_up = (ULONG) mcomp[c_ref].componentRef; num_elems = (ULONG) mcomp[c_ref].numOfComponents; /* * store the startposition of the corresponding melem table and * the number of elements in the IEtable */ globs->iei_ctx[rlevel].melemStart = (USHORT) look_up; globs->iei_ctx[rlevel].ieTableLen = (USHORT) num_elems; globs->iei_ctx[rlevel].EOCPending = FALSE; globs->iei_ctx[rlevel].countSkipped = 0; /* * for each element with an iei (ident) setup the * the iei_table-entry. */ ie_table_idx = 0; /* * if the number of IE in this message is greater than * the allocated IEItable, generate an error. */ if (num_elems > MAX_IE_PER_MSG) ccd_setError (globs, ERR_INTERNAL_ERROR, BREAK, (USHORT) -1); while (num_elems--) { if (melem[look_up].ident NEQ 0xffff) { globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident = (UBYTE) melem[look_up].ident; /* * GSM1TV elements have only a 4 bit Tag (T). For this * elements we have to shift the ident into the upper nibble * and set the lower nibble to zero. For GSM2T elements and * GSM1TV elements set the MSBit (Bit7). */ if (melem[look_up].codingType EQ CCDTYPE_GSM1_TV) { /* * shift into the upper nibble, clear the lower nibble * and set the MSBit. */ globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident <<= 4; globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident |= 0x80; globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident &= 0xf0; } else { if (melem[look_up].codingType EQ CCDTYPE_GSM2_T) { /* * Set the MSBit. */ globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident |= 0x80; } } globs->iei_ctx[rlevel].iei_table[ie_table_idx].act_amount = 0; globs->iei_ctx[rlevel].iei_table[ie_table_idx].exhausted = FALSE; switch (melem[look_up].codingType) { case CCDTYPE_GSM1_TV: case CCDTYPE_GSM2_T: case CCDTYPE_GSM3_TV: case CCDTYPE_GSM4_TLV: case CCDTYPE_GSM5_TV: case CCDTYPE_GSM5_TLV: case CCDTYPE_GSM1_ASN: case CCDTYPE_GSM6_TLV: globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid = TRUE; break; default: globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid = FALSE; break; } } else globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid = FALSE; #ifdef DEBUG_CCD TRACE_CCD (globs, "iei_table[%d] v=%d ident=%x level=%d", ie_table_idx, globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid, globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident, rlevel); #endif look_up++; ie_table_idx++; } globs->iei_ctx[rlevel].valid = TRUE; } } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* Attention for RUN_...: static function */ /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_search_table | +--------------------------------------------------------------------+ PURPOSE : search on the iei_table for the given TAG (T). if the TAG can be found (and - in case of CCDTYPE_GSM1_ASN - if the information element isn't exhausted), the table index was returned as a difference between the found index and the aktIndex, -127 otherwise. */ static int cdc_search_table ( int akt_index, ULONG t, BOOL limited, BOOL *nonTaggedFound, T_CCD_Globs *globs ) { int tab_idx; ULONG iei; int ret = -127; ULONG rec_level = globs->ccd_recurs_level; /* * search from the akt position to the end of the table. * This is faster, because in correct messages the found Tag * is at a later position in the table. */ tab_idx = akt_index; *nonTaggedFound = FALSE; while (tab_idx < (int) globs->iei_ctx[rec_level].ieTableLen) { #ifdef DEBUG_CCD TRACE_CCD (globs, "looking for Tag(%x) iei_table[%d] v=%d ident=%x level=%d", t, tab_idx, globs->iei_ctx[rec_level].iei_table[tab_idx].valid, globs->iei_ctx[rec_level].iei_table[tab_idx].ident, rec_level); #endif if (globs->iei_ctx[rec_level].iei_table[tab_idx].valid) { if (limited) { iei= (ULONG)(globs->iei_ctx[rec_level].iei_table[tab_idx].ident & 0x7f); } else { iei= (ULONG)(globs->iei_ctx[rec_level].iei_table[tab_idx].ident); } if ( iei EQ t ) { if ( globs->iei_ctx[rec_level].iei_table[tab_idx].exhausted EQ FALSE ) { return (tab_idx-akt_index); } else if ( (globs->iei_ctx[rec_level].melemStart + akt_index) EQ (int) globs->iei_ctx[rec_level].melemLast) { /* * allows multiple appearance of the repeated element is coded as * TLV0 TLV1 TLV2 .... */ return (tab_idx-akt_index); } else { ret = (tab_idx-akt_index); } } } else *nonTaggedFound = TRUE; tab_idx++; } tab_idx = 0; while (tab_idx < akt_index) { #ifdef DEBUG_CCD TRACE_CCD (globs, "looking for Tag(%x) iei_table[%d] v=%d ident=%x level=%d", t, tab_idx, globs->iei_ctx[rec_level].iei_table[tab_idx].valid, globs->iei_ctx[rec_level].iei_table[tab_idx].ident, rec_level); #endif if (limited) { iei= (ULONG)(globs->iei_ctx[rec_level].iei_table[tab_idx].ident & 0x7f); } else { iei= (ULONG) globs->iei_ctx[rec_level].iei_table[tab_idx].ident; } if (globs->iei_ctx[rec_level].iei_table[tab_idx].valid AND (iei EQ t) ) { if ( globs->iei_ctx[rec_level].iei_table[tab_idx].exhausted EQ FALSE ) { return (tab_idx-akt_index); } else { ret = (tab_idx-akt_index); } } tab_idx++; } if (ret != -127) { globs->SequenceError = TRUE; } return ret; } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* Attention for RUN_...: static function */ /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_decode_L | +--------------------------------------------------------------------+ PURPOSE : Decode the length element of TLV and LV values */ static ULONG cdc_decode_L (const ULONG e_ref, const ULONG len_l, T_CCD_Globs *globs) { ULONG l; switch (melem[e_ref].codingType) { case CCDTYPE_GSM1_ASN: l = (ULONG) bf_decodeByteNumber (8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "decoding 8 bits, l = (%x)", l); #endif if (l EQ 0x80) l = 0xFFFF; else if (l EQ 0x81) { l = (ULONG) bf_decodeByteNumber (8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "decoding 8 bits after 0x81, l = (%x)", l); #endif } else if (l EQ 0x82) { l = bf_decodeShortNumber (16, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "decoding 16 bits after 0x82, l = (%x)", l); #endif } break; case CCDTYPE_GSM5_TLV: l = (ULONG) bf_decodeByteNumber (8, globs); if (l EQ 0x81) { l = (ULONG) bf_decodeByteNumber (8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "decoding 8 bits after 0x81, l = (%x)", l); } else { TRACE_CCD (globs, "decoding 8 bits, l = (%x)", l); #endif } break; case CCDTYPE_GSM6_TLV: l = bf_decodeShortNumber (16, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "decoding 16 bits, l = (%x)", l); #endif break; default: l = (ULONG) bf_decodeByteNumber (len_l, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "decoding %d bits, l = (%x)", len_l, l); #endif break; } /* * Write the value of l at the end of UPN Stack. * this could be read by an IE of the coding type NO_CODE. */ globs->KeepReg[0] = l ; return l; } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* Attention for RUN_...: static function */ /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_tagged_LV_decode| +--------------------------------------------------------------------+ PURPOSE : If the parameter lenL is set to a positive value, this function decodes the L-component. After this it decodes the element referenced by eRef out of the bitstream into the C-Structure (globs->pstruct) at position globs->pstructOffs. If a repeat value is defined for this element, this function decodes only one appeareance of the element because it is a tagged element. In this case the decoded element is stored in an array wich is indexed by eIndex; */ static BOOL cdc_tagged_LV_decode (const ULONG e_ref, ULONG e_index, const ULONG len_l, T_CCD_Globs *globs) { ULONG amount, l; USHORT act_maxBP, tmp_maxBP; BOOL endOfComposition = FALSE; BOOL asn1=FALSE; U32 offset=0; #ifdef DYNAMIC_ARRAYS U8 *old_pstruct = NULL; #endif if (melem[e_ref].codingType EQ CCDTYPE_GSM1_ASN) asn1 = TRUE; if (melem[e_ref].elemType NEQ 'S') { /* * set the offset into the C-structure for this element. */ if (melem[e_ref].optional) { globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE; } if (melem[e_ref].repType EQ 'i') { /* * The number of appearance of all repeatable IEs may * differ in a message. So we have to store the number * in a c_xxx counter into the C-Structure. */ if (melem[e_ref].maxRepeat > 65535) *(ULONG *) (globs->pstruct + globs->pstructOffs++) = e_index; else if (melem[e_ref].maxRepeat > 255) *(USHORT *) (globs->pstruct + globs->pstructOffs++) = (USHORT) e_index; else globs->pstruct[globs->pstructOffs] = (UBYTE) e_index; globs->pstructOffs++; /* * Recalculate the struct offset for repeatable IEs. * New pointer types 'R' and 'F' are equivalent to 'V'. */ #ifdef DYNAMIC_ARRAYS offset = (e_index-1) * ((melem[e_ref].elemType EQ 'V' OR melem[e_ref].elemType EQ 'R' OR melem[e_ref].elemType EQ 'F' ) ? mvar[melem[e_ref].elemRef].cSize : mcomp[melem[e_ref].elemRef].cSize ); #else offset = (e_index-1) * ((melem[e_ref].elemType EQ 'V') ? mvar[melem[e_ref].elemRef].cSize : mcomp[melem[e_ref].elemRef].cSize ); #endif } } /* * If len_l > 0 read the l-Component out of the bistream. */ if (len_l) { if( len_l <= (ULONG) (globs->maxBitpos - globs->bitpos) ) { act_maxBP = globs->maxBitpos; l = cdc_decode_L (e_ref, len_l, globs); if (l EQ 0xFFFF) { /* * For ASN1-BER encoding we must look for the special * length 0x80 because it indicates the indefinite * length. This needs a special handling with later EOC tags. * */ globs->iei_ctx[globs->ccd_recurs_level].EOCPending = TRUE; globs->numEOCPending++; #ifdef DEBUG_CCD TRACE_CCD (globs, "implicit ASN1 length - EOC is pending"); #endif } else { /* * Calculate the max bitpos for this element */ tmp_maxBP = (USHORT) (globs->bitpos + (l*8)); if (globs->buflen < tmp_maxBP) { ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } else if (globs->maxBitpos < tmp_maxBP) { ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } globs->maxBitpos = (USHORT)MINIMUM (globs->buflen, tmp_maxBP); tmp_maxBP = globs->maxBitpos; } } else { ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } } #ifdef DYNAMIC_ARRAYS /* * Check for pointer types; allocate memory if necessary. */ if ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR (melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F')) { U32 cSize; U8 *addr; /* * Find size to allocate; * - Read from mcomp or mvar according to type */ cSize = (ULONG)((melem[e_ref].elemType EQ 'V' OR melem[e_ref].elemType EQ 'R') ? mvar[melem[e_ref].elemRef].cSize : mcomp[melem[e_ref].elemRef].cSize ); /* * Allocate additional memory */ addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS); /* If no memory, log error and return immediately */ if (addr EQ NULL) { ccd_setError (globs, ERR_NO_MEM, BREAK, (USHORT) -1); return endOfComposition; } else memset (addr, 0, (size_t)(cSize)); /* * Memory allocated; * 1. Save old "globs->pstruct" variables * 2. Store pointer to freshly allocated memory area in structure * 3. Initialize pstruct to point to the freshly allocated memory area. * 4. Initialize pstructOffs to 0 to start decoding at offset 0 * in the new memory area. */ old_pstruct = globs->pstruct; *(U8 **)(globs->pstruct + globs->pstructOffs) = addr; globs->pstruct = addr; globs->pstructOffs = 0; } else { globs->pstructOffs += offset; } #else /* DYNAMIC_ARRAYS */ globs->pstructOffs += offset; #endif /* DYNAMIC_ARRAYS */ /* * Decode the value. Keep caution with BER encoding of ASN1 integers. * All other types can be decoded by a generic function. */ if (asn1 AND melem[e_ref].elemType EQ 'V' AND melem[e_ref].repType EQ ' ' AND l NEQ 0xFFFF ) { #ifdef DEBUG_CCD #ifdef CCD_SYMBOLS TRACE_CCD (globs, "BER decoding of ASN.1 integer %s", ccddata_get_alias((USHORT) e_ref, 1)); #else TRACE_CCD (globs, "BER decoding of ASN.1 integer; e_ref = %d", melem[e_ref].elemRef); #endif #endif if (mvar[melem[e_ref].elemRef].cType EQ 'X') bf_readBitChunk (l*8, globs); else bf_readBits (l*8, globs); } else { amount = 1; if (len_l) { if (l > 0) { cdc_decodeElemvalue (e_ref, &amount, globs); } else { amount = 0; } } else { if (melem[e_ref].codingType != CCDTYPE_GSM2_T) cdc_decodeElemvalue (e_ref, &amount, globs); } } #ifdef DYNAMIC_ARRAYS /* * Restore globs->pstruct for possible use below */ if (old_pstruct NEQ NULL) globs->pstruct = old_pstruct; #endif if (asn1 AND globs->numEOCPending AND !bf_endOfBitstream(globs)) { UBYTE T = bf_decodeByteNumber (8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "looking for EOC decoding 8 bits T = (%x)", T); #endif if (T EQ 0) { #ifdef DEBUG_CCD TRACE_CCD (globs, "First EOC octet found"); #endif if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) { #ifdef DEBUG_CCD TRACE_CCD (globs, "End of ASN1 TLV"); #endif /* * Skip the second EOC octet. */ bf_incBitpos (8, globs); globs->iei_ctx[globs->ccd_recurs_level].EOCPending = FALSE; globs->numEOCPending--; } else { /* * The read first EOC octet belongs to an ASN1 TLV of a * higher recursion level. Let it be read and evalauted later * again for that IE. */ bf_setBitpos (globs->bitpos-8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "End of higer level ASN1 TLV"); TRACE_CCD (globs, "Decrementing bitpos by 8 to %d", globs->bitpos); #endif endOfComposition = TRUE; } } else { if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) { /* * EOC element is pending but not found. */ ccd_setError (globs, ERR_EOC_TAG_MISSING, BREAK, (USHORT) T, globs->bitpos-8, (USHORT) -1); bf_setBitpos (globs->bitpos-8, globs); } else { /* * normal TAG leave it in the bitstream */ #ifdef DEBUG_CCD TRACE_CCD (globs, "Normal TAG - Decrementing bitpos by 8 to %d", globs->bitpos); #endif bf_setBitpos (globs->bitpos-8, globs); } } } if (len_l) { if (!asn1) { if (globs->bitpos > tmp_maxBP) { ccd_recordFault (globs, ERR_ELEM_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } else { /* * set the bitpos to the end of the LV or TLV element */ bf_setBitpos (tmp_maxBP, globs); } } /* * set the maxBitpos to the next octet boundary if the * last non-spare IE does not end at an octet boundary. * This is necessary for avoiding an early end of decoding. */ /* globs->maxBitpos = globs->buflen; */ globs->maxBitpos = act_maxBP; } return endOfComposition; } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* Attention for RUN_...: static function */ /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_normal_LV_decode| +--------------------------------------------------------------------+ PURPOSE : If the parameter lenL is set, this function decodes the L-component. After this it decodes the element referenced by eRef from the bitstream into the C-Structure (globs->pstruct) at position globs->pstructOffs. If a repeat value is defined for this element this function decodes the V-component multiple and stores the values into an array. */ static BOOL cdc_normal_LV_decode (const ULONG e_ref, const ULONG len_l, T_CCD_Globs *globs) { ULONG l, repeat, amount, max_rep; USHORT act_maxBP, tmp_maxBP; BOOL is_variable; BOOL endOfComposition = FALSE; BOOL asn1; BOOL length_in_bits; #ifdef DYNAMIC_ARRAYS U8 *old_pstruct = NULL; #endif switch (melem[e_ref].codingType) { case CCDTYPE_GSM1_ASN: asn1 = TRUE; length_in_bits = FALSE; break; case CCDTYPE_GSM7_LV: asn1 = FALSE; length_in_bits = TRUE; break; default: asn1 = FALSE; length_in_bits = FALSE; break; } /* * if this element is repeatable, and the number of * repeats depends on another element, calculate the repeater */ if (melem[e_ref].repType NEQ ' ') { is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs); } else { repeat = 1; is_variable = FALSE; } if (melem[e_ref].elemType NEQ 'S') { /* * Element is not a SPARE. * Setup the offset into the C-structure for this element */ if (melem[e_ref].optional) { globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE; } if (is_variable) { /* * for variable sized elements store the min-value * as counter into the C-Structure (c_xxx). */ if (max_rep > 65535) *(ULONG *) (globs->pstruct + globs->pstructOffs++) = repeat; else if (max_rep > 255) *(USHORT *) (globs->pstruct + globs->pstructOffs++) = (USHORT) repeat; else globs->pstruct[globs->pstructOffs] = (UBYTE) repeat; globs->pstructOffs++; } } /* * if len_l > 0 read the l-Component out of the bistream. */ if (len_l) { if( len_l <= (ULONG)(globs->maxBitpos - globs->bitpos) ) { act_maxBP = globs->maxBitpos; l = cdc_decode_L (e_ref, len_l, globs); if (l EQ 0xFFFF) { /* * for ASN1 element coding we must look for the special * length 0x80 because it indicates the indefinite * length. This needs a special handling with later EOC tags. */ globs->iei_ctx[globs->ccd_recurs_level].EOCPending = TRUE; globs->numEOCPending++; #ifdef DEBUG_CCD TRACE_CCD (globs, "implicit ASN1 length - EOC is pending"); #endif } else { /* * calculate the max bitpos for this element */ if (!length_in_bits) l *= 8; tmp_maxBP = (USHORT) (globs->bitpos + l); if (globs->buflen < tmp_maxBP) { ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } else if (globs->maxBitpos < tmp_maxBP) { ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } globs->maxBitpos = (USHORT)MINIMUM (globs->buflen, tmp_maxBP); tmp_maxBP = globs->maxBitpos; /* * for bitfields which appear in TLV or LV elements * we must calculate the length (repeat) from the l values */ if (melem[e_ref].repType EQ 'b') repeat = l; } } else { ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } } #ifdef DYNAMIC_ARRAYS /* * MVJ: Dynamic array addition. * Check for pointer types; allocate memory if necessary. */ if ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR (melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F')) { ULONG cSize, rep; U8 *addr; /* * Find size to allocate; * - Read from mcomp or mvar according to type * - Unbounded (0-terminated) ASN1-types are allocated with MAX repeat */ if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) { rep = (ULONG) melem[e_ref].maxRepeat; } else { rep = repeat; } cSize = (ULONG)((melem[e_ref].elemType EQ 'V' OR melem[e_ref].elemType EQ 'R') ? mvar[melem[e_ref].elemRef].cSize : mcomp[melem[e_ref].elemRef].cSize ) * rep; /* * Allocate additional memory */ addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS); /* If no memory, log error and return immediately */ if (addr EQ NULL) { ccd_setError (globs, ERR_NO_MEM, BREAK, (USHORT) -1); return endOfComposition; } else memset (addr, 0, (size_t)cSize); /* * Memory allocated; * 1. Save old "globs->pstruct" variables * 2. Store pointer to freshly allocated memory area in structure * 3. Initialize pstruct to point to the freshly allocated memory area. * 4. Initialize pstructOffs to 0 to start decoding at offset 0 * in the new memory area. */ old_pstruct = globs->pstruct; *(U8 **)(globs->pstruct + globs->pstructOffs) = addr; globs->pstruct = addr; globs->pstructOffs = 0; } #endif /* * Decode the value. Keep caution with BER encoding of ASN1 integers. * All other types can be decoded by a generic function. */ if (asn1 AND melem[e_ref].elemType EQ 'V' AND melem[e_ref].repType EQ ' ' AND l NEQ 0xFFFF ) { #ifdef DEBUG_CCD #ifdef CCD_SYMBOLS TRACE_CCD (globs, "BER decoding of ASN.1 integer %s", ccddata_get_alias((USHORT) e_ref, 1)); #else TRACE_CCD (globs, "BER decoding of ASN.1 integer; e_ref = %d", melem[e_ref].elemRef); #endif #endif amount = l; if (mvar[melem[e_ref].elemRef].cType EQ 'X') bf_readBitChunk (l, globs); else bf_readBits (l, globs); } else { amount = repeat; if (len_l) { if (l > 0) { cdc_decodeElemvalue (e_ref, &amount, globs); } else { amount = 0; } } else { if (melem[e_ref].codingType != CCDTYPE_GSM2_T) cdc_decodeElemvalue (e_ref, &amount, globs); } } #ifdef DYNAMIC_ARRAYS /* * Restore globs->pstruct for possible use below */ if (old_pstruct NEQ NULL) { globs->pstruct = old_pstruct; } #endif if (amount NEQ repeat AND is_variable) { /* * If the number of decoded elements is not equal to the given * repeat value, because the bitstream or the IE ended, * store the new c_xxx value. */ globs->pstructOffs = melem[e_ref].structOffs; if (melem[e_ref].optional) globs->pstructOffs++; globs->pstruct[globs->pstructOffs] = (UBYTE) amount; if (melem[e_ref].repType NEQ 'i') { /* * if this element is not of the repeat style 'interval' * ([X..Y] where X and Y are constants) we have to generate * an ccd error because some outstanding repeats are missing. */ ccd_setError (globs, ERR_MAND_ELEM_MISS, CONTINUE, (USHORT) -1); } } if (asn1 AND globs->numEOCPending AND !bf_endOfBitstream(globs)) { UBYTE T = bf_decodeByteNumber (8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "looking for EOC decoding 8 bits T = (%x)", T); #endif if (T EQ 0) { #ifdef DEBUG_CCD TRACE_CCD (globs, "First EOC octet found"); #endif if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) { #ifdef DEBUG_CCD TRACE_CCD (globs, "End of ASN1 TLV"); #endif /* * Skip the second EOC octet. */ bf_incBitpos (8, globs); globs->iei_ctx[globs->ccd_recurs_level].EOCPending = FALSE; globs->numEOCPending--; } else { /* * The read first EOC octet belongs to an ASN1 TLV of a * higher recursion level. Let it be read and evalauted later * again for that IE. */ bf_setBitpos (globs->bitpos-8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "End of higer level ASN1 TLV"); TRACE_CCD (globs, "Decrementing bitpos by 8 to %d", globs->bitpos); #endif endOfComposition = TRUE; } } else { if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) { /* * EOC element is pending but not found. */ ccd_setError (globs, ERR_EOC_TAG_MISSING, BREAK, (USHORT) T, globs->bitpos-8, (USHORT) -1); bf_setBitpos (globs->bitpos-8, globs); } else { /* * normal TAG leave it in the bitstream */ #ifdef DEBUG_CCD TRACE_CCD (globs, "Normal TAG - Decrementing bitpos by 8 to %d", globs->bitpos); #endif bf_setBitpos (globs->bitpos-8, globs); } } } if (len_l) { if (!asn1) { if (globs->bitpos > tmp_maxBP) { ccd_recordFault (globs, ERR_ELEM_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } else { /* * set the bitpos to the end of the LV or TLV element */ bf_setBitpos (tmp_maxBP, globs); } } /* * set the maxBitpos to the next octet boundary if the * last non-spare IE does not end at an octet boundary. * This is necessary for avoiding an early end of decoding. */ /* globs->maxBitpos = globs->buflen; */ globs->maxBitpos = act_maxBP; } return endOfComposition; } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* Attention for RUN_...: static function */ /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_skipElem | +--------------------------------------------------------------------+ PURPOSE : Skip an element referenced by eRef. This function perform a decoding of this element, but not into the target C-Structure. A dummy C-Structure is used instead. The complete decoding is necesary, because there is no information about the length of this element. B.t.w. for mandatory elements with fixed length, we can calculate the length, for optional elements or for variable sized arrays or bitbuffers it is impossible without decoding the entire element. */ static void cdc_skipElem (const ULONG e_ref, const ULONG len_l, T_CCD_Globs *globs) { UBYTE *ActStructAddr; U32 ActStructOffs; #ifdef DEBUG_CCD TRACE_CCD (globs, "skipping element %d", melem[e_ref].elemRef); #endif ActStructAddr = globs->pstruct; ActStructOffs = globs->pstructOffs; globs->pstruct = dummy; globs->pstructOffs = 0; cdc_tagged_LV_decode (e_ref, 1, len_l, globs); globs->pstruct = ActStructAddr; globs->pstructOffs = ActStructOffs; } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_tlv_decode | +--------------------------------------------------------------------+ PURPOSE : Decoding of the T-components of T TV and TLV typed information elements. The len determines the length of the T component. This function returns the index (reference) of the rigth element. If the iei is not known in this composition (msg or submsg) an error handling is done and NO_REF is returned. */ SHORT cdc_tlv_decode (const ULONG c_ref, const ULONG e_ref, const T_TLV_SORT *tlv_inf, T_CCD_Globs *globs) { ULONG repeat, max_rep; ULONG ie_amount, l, len_l, len_t, t; BOOL is_variable, nonTagged, limitSearch=FALSE; UBYTE CR=FALSE; SHORT IdxOffset = 0; int ieTableIdx; BOOL asn1, non_std_tag; SHORT ret; ULONG cix_ref, num_prolog_steps, prolog_step_ref; /* .../src/linux/include/asm/current.h defines a macro 'current' */ T_UNKNOWN_TAG *first, *currentTag; /* * Set the flag for the type of extension which is to expect * at the end of the message. */ globs->SeekTLVExt = TRUE; /* Set ref number for calcidx table. */ cix_ref = melem[e_ref].calcIdxRef; num_prolog_steps = calcidx[cix_ref].numPrologSteps; prolog_step_ref = calcidx[cix_ref].prologStepRef; /* * if this element is conditional, check the condition */ if (calcidx[cix_ref].numCondCalcs NEQ 0 AND ! ccd_conditionOK (e_ref, globs)) return 1; len_t = 8; switch (melem[e_ref].codingType) { case CCDTYPE_GSM1_ASN: asn1 = TRUE; non_std_tag = FALSE; len_l = 8; break; case CCDTYPE_GSM5_TV: case CCDTYPE_GSM5_TLV: non_std_tag = TRUE; asn1 = FALSE; len_l = 8; break; case CCDTYPE_GSM6_TLV: non_std_tag = FALSE; asn1 = FALSE; len_l = 16; break; case CCDTYPE_GSM7_LV: non_std_tag = FALSE; asn1 = FALSE; len_l = 7; break; default: asn1 = FALSE; non_std_tag = FALSE; len_l = 8; break; } /* * if this element have a defined Prolog * we have to process it before decoding the bitstream */ if (num_prolog_steps) { ccd_performOperations (num_prolog_steps, prolog_step_ref, globs); } if (tlv_inf->gotTag) { /* * tagged element */ len_t = 8; /* * initialize the iei_table for each new message */ if (globs->ccd_recurs_level NEQ globs->last_level) { cdc_init_table (c_ref, globs); globs->TagPending = FALSE; globs->SequenceError = FALSE; globs->last_level = globs->ccd_recurs_level; } /* * calculate the index into the ieTable for this element */ ieTableIdx = (int)(e_ref - globs->iei_ctx[globs->ccd_recurs_level].melemStart); if (globs->TagPending) { /* * if we previously read a t value and does not processed it * get this pending tag. */ t = (ULONG) globs->PendingTag; globs->TagPending = FALSE; } else { /* * read the information element identifier out of the bitstream. * If the first bit (MSBit) of the t-component is set, it is * a Tag of a TYPE1 or TYPE2 element. */ t = (ULONG) bf_decodeByteNumber (8, globs); if (!asn1 AND !non_std_tag AND (t & 0x80) EQ 0x80 AND (t & 0xA0) NEQ 0xA0) { ULONG Tag4 = t & 0xf0; /* * MSBit is set. We have to check if the Tag value can * be found as a 4 bit or 8 bit value in the IEI-table. */ if (cdc_search_table (ieTableIdx, Tag4, limitSearch, &nonTagged, globs) NEQ -127) { /* * Tag found as a 4 bit value. Decrement the readpointer * of the bitstream by 4, because we have read out 4 bits * to much. */ bf_setBitpos (globs->bitpos-4, globs); t = Tag4; len_t =4; #ifdef DEBUG_CCD TRACE_CCD (globs, "4 bit Tag decrementing bitpos by 4 to %d", globs->bitpos); #endif } } } #ifdef DEBUG_CCD TRACE_CCD (globs, "reading t = 0x%X", t); #endif if (melem[e_ref].codingType EQ CCDTYPE_GSM5_TLV) { limitSearch = TRUE; CR = (UBYTE) (((t & 0x80) EQ 0x80) ? TRUE : FALSE); t &= 0x7f; } if (asn1 AND t EQ 0x00) { /* * This is for ASN1 element coding the special * End Of Component Tag (EOC). The following length must be zero. */ bf_setBitpos (globs->bitpos-8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "ASN1 End of Component found belongs to higher TLV"); TRACE_CCD (globs, "leaving this level and decrementing bitpos by 8 to %d", globs->bitpos); #endif return END_OF_COMPOSITION; /* skip the remaining elements in this level */ } /* asn1 and EOC */ else { if ((IdxOffset = (SHORT) cdc_search_table (ieTableIdx, t, limitSearch, &nonTagged, globs)) == -127) { /* * t (iei) not defined in this composition (msg or submsg) */ if (asn1) { if (melem[mcomp[c_ref].componentRef + mcomp[c_ref].numOfComponents -1].codingType == CCDTYPE_GSM5_V) { /* Restore the old bitposition (before the 'TAG') and return * IdxOffset to jump to last element of the composition. * The coding type of this elements is CCDTYPE_GSM5_V */ bf_setBitpos (globs->bitpos-8, globs); IdxOffset = (SHORT)(mcomp[c_ref].numOfComponents - ieTableIdx - 1); return (IdxOffset); } /* * for recursive ASN.1 structs it is possible that the foreign * tag belongs to a upper level composition of element. * * * Restore the old bitposition (before the TAG) and return * END_OF_COMPOSITION to leave this composition level */ bf_setBitpos (globs->bitpos-8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "Unknown Tag. It may belong to upper ASN.1 comp -> dec. bitpos by 8 to %d", globs->bitpos); #endif return END_OF_COMPOSITION; /* skip the remaining elements in this level */ } else if (nonTagged) { U16 actBitpos; actBitpos = globs->bitpos-8; if (melem[mcomp[c_ref].componentRef + mcomp[c_ref].numOfComponents -1].codingType == CCDTYPE_GSM5_V && melem[e_ref].codingType EQ CCDTYPE_GSM5_TLV) { #if defined (CCD_TEST) currentTag = (T_UNKNOWN_TAG *) malloc(sizeof(T_UNKNOWN_TAG)); #else currentTag = (T_UNKNOWN_TAG *) D_ALLOC(sizeof(T_UNKNOWN_TAG)); #endif first = currentTag; currentTag->bitpos = globs->bitpos-8; currentTag->errCode = ERR_NO_MORE_ERROR; currentTag->next = NULL; /* unknown GSM Type TLV -> skip 'l' bytes */ /* at least 8 bits must remain for following expeceted tagged element */ while (globs->maxBitpos - 8 - globs->bitpos >= 8) { currentTag->bitpos = globs->bitpos-8; currentTag->tag = (UBYTE) t; /* * Expecting a CCDTYPE_GSM5_TLV type we get an unknown tag with MSB set. * Store bitpos and t for the application (SAT) for the handling of * comprehension required elements. */ if (CR) { // save (ERR_COMPREH_REQUIRED; globs->bitpos-len_t) currentTag->errCode = ERR_COMPREH_REQUIRED; } else { // save (ERR_IE_NOT_EXPECTED; globs->bitpos-len_t) currentTag->errCode = ERR_IE_NOT_EXPECTED; } l = (ULONG) bf_decodeByteNumber (8, globs); bf_incBitpos ((l << 3) , globs); t = (ULONG) bf_decodeByteNumber (8, globs); limitSearch = TRUE; CR = (UBYTE) (((t & 0x80) EQ 0x80) ? TRUE : FALSE); t &= 0x7f; if (cdc_search_table (ieTableIdx, t, limitSearch, &nonTagged, globs) != -127) { bf_setBitpos (globs->bitpos-8, globs); // set all ccd Errors do { currentTag = first; ccd_setError (globs, currentTag->errCode, CONTINUE, (USHORT) currentTag->tag, currentTag->bitpos, (USHORT) -1); first = currentTag->next; #if defined (CCD_TEST) free(currentTag); #else D_FREE(currentTag); #endif } while (first != NULL ); return 0; } else { #if defined (CCD_TEST) currentTag->next = (T_UNKNOWN_TAG *) malloc(sizeof(T_UNKNOWN_TAG)); #else currentTag->next = (T_UNKNOWN_TAG *) D_ALLOC(sizeof(T_UNKNOWN_TAG)); #endif currentTag = currentTag->next; currentTag->next = NULL; } } do { currentTag = first; first = currentTag->next; #if defined (CCD_TEST) free(currentTag); #else D_FREE(currentTag); #endif } while (first != NULL ); } /* * a non tagged element is possible in the message. If the tag * can not be found, the tag may be the beginning of the non tagged * element. E.g. rest octetts in sysinfo 4 * * Restore the old bitposition (before the TAG) and return 1 to * go to the next element. */ bf_setBitpos (actBitpos, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "Unknown Tag but mand. IE possible -> dec. bitpos by 8 to %d", globs->bitpos); #endif return 1; } /* * Otherwise look if it is a type 1,2 or 4 Element */ if ((t & 0x80) EQ 0x80) { /* MSBit set -> GSM Type 1 or Type2 -> skip 1 byte */ /* position already incremented by decoding the TAG value */ } /* Just another reason for getting IdxOffset equal to 0. */ else if (globs->ccd_recurs_level >= MAX_RECURSIONS_PER_MSG) { ccd_setError (globs, ERR_INTERNAL_ERROR, BREAK, (USHORT) -1); } else { /* * Expecting a CCDTYPE_GSM5_TLV type we get an unknown tag with MSB set. * Store bitpos and t for the application (SAT) for the handling of * comprehension required elements. */ if (CR) { ccd_setError (globs, ERR_COMPREH_REQUIRED, CONTINUE, (USHORT) t, (USHORT) globs->bitpos-len_t, (USHORT) -1); } /* * 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. * Store bitpos and t for the application for the handling of comprehension * required elements. */ else if ((t & 0x70) EQ 0 AND melem[e_ref].codingType NEQ CCDTYPE_GSM5_TLV) { ccd_setError (globs, ERR_COMPREH_REQUIRED, CONTINUE, (USHORT) t, (USHORT) globs->bitpos-len_t, (USHORT) -1); } /* * We get an unknown tag and any sort of comprehension required flag is set. * Store bitpos and t for the application */ else { ccd_setError (globs, ERR_IE_NOT_EXPECTED, CONTINUE, (USHORT) t, (USHORT) globs->bitpos-len_t, (USHORT) -1); } /* MSBit cleared -> GSM Type TLV -> skip 'l' bytes */ if (globs->maxBitpos - globs->bitpos >= 8) { l = (ULONG) bf_decodeByteNumber (8, globs); bf_incBitpos ((l << 3) , globs); } else { ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } } /* * return 0 -> that means try it again with this actual element * referenced by e_ref */ return 0; } /* tag not found */ else { T_IEI_TABLE *iei_tbl = &globs->iei_ctx[globs->ccd_recurs_level].iei_table[ieTableIdx]; /* * element definition for this iei found */ if (IdxOffset NEQ 0) { /* * found index differs from the actual index */ globs->TagPending = TRUE; globs->PendingTag = (UBYTE) t; if (!asn1 AND IdxOffset < 0) { /* * found an element in wrong sequence * (for ASN1 elements the sequence order is not relevant) */ ccd_setError (globs, ERR_IE_SEQUENCE, (UBYTE) ((asn1) ? BREAK : CONTINUE), (USHORT) t, (USHORT) globs->bitpos-len_t, (USHORT) -1); globs->SequenceError = TRUE; } if (globs->SequenceError) { globs->RefBeforeError = (USHORT) e_ref; } if (asn1) { globs->iei_ctx[globs->ccd_recurs_level].countSkipped += IdxOffset; } /* * skip to the found element */ return (IdxOffset); } else { globs->iei_ctx[globs->ccd_recurs_level].melemLast = (USHORT) e_ref; if (iei_tbl->act_amount == 0) { /* * first apearance of this iei * calculate the upper and lower boundaries and the * facility of multiple appearance of this tagged element * in the bitstream. */ /* * The element is repeatable. There are three kinds of * repeat definitions valid for standard elements: * [5] - The element is repeated 5 times. * [0..5] - The element is repeated 0 to 5 times. * [a..5] - The element is repeated "the value of a" times. * * For tagged elements the following processing is defined: * * [5] - The t-Component is decoded * (maybe the l-Component too (if defined one). * After this the V-component of the element * is decoded 5 times. * * [0..5] - The t- and maybe the l-Component are decoded. * After this one V-Component is decoded and it * is stored as an array entry into * the target C-Structure. In this case the * parameter ieIndex gives the index into * this array, where the element has to * be written into. * * [a..5] - The t- and maybe the l-Component are decoded. * After this one V-Component is decoded * "a" times and is stored into the C-Structure * as an array. * */ switch (melem[e_ref+IdxOffset].repType) { case 'i': /* * multiapearance of this element. The V-component is * repeated once */ is_variable = ccd_calculateRep (e_ref+IdxOffset, &repeat, &max_rep, globs); iei_tbl->max_amount = (UBYTE) max_rep; iei_tbl->multiple = TRUE; break; case 'v': case 'b': default: /* * if this element is repeatable, and the number of * repeats depends on another element, the valid amount * of this element is 1 and the V-component will be * repeated. */ iei_tbl->max_amount = 1; iei_tbl->multiple = FALSE; break; } iei_tbl->act_amount = 1; } if (iei_tbl->act_amount <= iei_tbl->max_amount) { /* * process only the max_amount appearances of each element. * All additional IEs are ignored. */ ie_amount = (ULONG)(iei_tbl->act_amount)++; } else { if (asn1) { /* For ASN1 elements the sequence order is not relevant. * It is possible that the tag belongs to an upper level * composition of elements. * Restore the old bitposition (before the TAG) and return * END_OF_COMPOSITION to leave this composition level */ bf_setBitpos (globs->bitpos-8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "Tag may belong to upper ASN.1 comp -> dec. bitpos by 8 to %d", globs->bitpos); #endif return END_OF_COMPOSITION; /* skip the remaining elements in this level */ } else { ie_amount = 0; ccd_setError (globs, ERR_MAX_IE_EXCEED, CONTINUE, (USHORT) t, (USHORT) globs->bitpos-len_t, (USHORT) -1); } } /* * The t-component matches with the defined identifier for * the actual element definition (e_ref). */ if (globs->SequenceError) { globs->SequenceError = FALSE; if (asn1) { /* For ASN1 elements the sequence order is not relevant. * It is possible that the tag belongs to an upper level * composition of elements. * Restore the old bitposition (before the TAG) and return * END_OF_COMPOSITION to leave this composition level */ bf_setBitpos (globs->bitpos-8, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "Tag may belong to upper ASN.1 comp -> dec. bitpos by 8 to %d", globs->bitpos); #endif return END_OF_COMPOSITION; /* skip the remaining elements in this level */ } else { /* found an element in wrong sequence */ cdc_skipElem (e_ref, (tlv_inf->gotLen ? len_l:0), globs); return (SHORT)(globs->RefBeforeError - e_ref); } } /* * if this element is conditional, check the condition */ if (calcidx[cix_ref].numCondCalcs NEQ 0 AND ! ccd_conditionOK (e_ref, globs)) { /* * if the condition for this element is not valid * but this element appears in the message, generate * an error and skip the element */ ccd_setError (globs, ERR_IE_NOT_EXPECTED, CONTINUE, (USHORT) t, (USHORT) globs->bitpos-len_t, (USHORT) -1); cdc_skipElem (e_ref, (tlv_inf->gotLen ? len_l:0), globs); return 0; } /* * check for a valid index */ if (ie_amount EQ 0) { /* * The max number of repeats are reached * In this case we must skip this element. */ cdc_skipElem (e_ref, (tlv_inf->gotLen ? len_l:0), globs); return 0; } if (iei_tbl->multiple) { if (melem[e_ref].elemType NEQ 'S') { /* * Element is not a SPARE * Setup the offset into the C-structure for this element */ globs->pstructOffs = melem[e_ref].structOffs; } ret = cdc_tagged_LV_decode (e_ref, ie_amount, (tlv_inf->gotLen ? len_l:0), globs); } else { if (melem[e_ref].elemType NEQ 'S') { /* * Element is not a SPARE * Setup the offset into the C-structure for this element */ globs->pstructOffs = melem[e_ref].structOffs; } ret = cdc_normal_LV_decode (e_ref, (tlv_inf->gotLen ? len_l:0), globs); } globs->SeekTLVExt = TRUE; iei_tbl->exhausted = TRUE; if (ret) return END_OF_COMPOSITION; /* * if more then one IE of this type are allowed, a ret of 0 * indicates the calling function (ccd_decodeComposition()) * to leave the pointer to the actual element definition on * this element. If the value of ret is greater then 0 the * calling function will increment the pointer by the value * of ret. * cdc_T_decode() has found the expected element definition. * Go to the next definition or stay at this definition, * if the occurance of this element is more than one. */ if (iei_tbl->act_amount > iei_tbl->max_amount) { iei_tbl->act_amount = 0; } if (iei_tbl->max_amount > 1) { return (0); } else { if (globs->iei_ctx[globs->ccd_recurs_level].countSkipped) { ret = (-1) * (globs->iei_ctx[globs->ccd_recurs_level].countSkipped); (globs->iei_ctx[globs->ccd_recurs_level].countSkipped) = 0; return (ret); } else { return (1); } } } /* IdxOffset == 0 */ } /* tag found */ } /* no asn1, no EOC */ } /* got tag */ else { /* * element has no t-component, process the l- and V-components */ if (melem[e_ref].elemType NEQ 'S') { /* * Element is not a SPARE * Setup the offset into the C-structure for this element */ globs->pstructOffs = melem[e_ref].structOffs; } ret = cdc_normal_LV_decode (e_ref, len_l, globs) ? END_OF_COMPOSITION : 1; globs->SeekTLVExt = TRUE; return ret; } } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_tlv_encode | +--------------------------------------------------------------------+ PURPOSE : if T_len > 0 this function encodes the T-Component of this element. If L_len > 0 it encodes the number of bytes uses for this element. After all the function encodes the V-component referenced by eRef from the C-Structure (globs->pstruct) at position globs->pstructOffs into the bitstream. */ void cdc_tlv_encode (const ULONG e_ref, UBYTE lenT, UBYTE lenL, T_CCD_Globs *globs) { ULONG posL=0, t_repeat, v_repeat, repeat; ULONG cSize, startOffset=0; BOOL multAppear; U8 *old_pstruct = NULL; ULONG i; ULONG cix_ref, num_prolog_steps, prolog_step_ref; cix_ref = melem[e_ref].calcIdxRef; num_prolog_steps = calcidx[cix_ref].numPrologSteps; prolog_step_ref = calcidx[cix_ref].prologStepRef; /* * If this element is conditional, check the condition. */ if (calcidx[cix_ref].numCondCalcs NEQ 0 AND ! ccd_conditionOK (e_ref, globs)) return; /* * If this element have a defined Prolog, * we have to process it before decoding the bit stream. */ if (num_prolog_steps) { ccd_performOperations (num_prolog_steps, prolog_step_ref, globs); } if (melem[e_ref].elemType NEQ 'S') { /* * Element is not a SPARE. * Setup the offset into the C-structure for this element. * In case of pointer types, the pstructOffs must be * the offset into the memory area pointed to. CCDGEN must * ensure this holds true. */ globs->pstructOffs = melem[e_ref].structOffs; if ( ! cdc_isPresent(e_ref, globs) ) return; if (melem[e_ref].repType EQ 'v' OR melem[e_ref].repType EQ 'i') { /* * for variable sized elements read the amount * of repeats out of the C-Structure (c_xxx). * If the number of repeats given by the C-Structure * exceeds the allowed value (maxRepeat) CCD gives a warning! */ if (melem[e_ref].maxRepeat > 255) { ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++)); repeat = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat); if (repeat < count) ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } else { repeat = (ULONG) MINIMUM (globs->pstruct[globs->pstructOffs], melem[e_ref].maxRepeat); if ( repeat < (ULONG) (globs->pstruct[globs->pstructOffs]) ) ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } globs->pstructOffs++; multAppear = (melem[e_ref].repType EQ 'i'); } else { /* * Field of constant length: repType EQ 'c' * or bit-field allocated with * given maximum length: repType EQ 'b' (often cType='X') */ repeat = (ULONG)((melem[e_ref].repType EQ 'c' OR melem[e_ref].repType EQ 'b') ? melem[e_ref].maxRepeat : 1 ); multAppear = FALSE; } /* * Perform pointer dereference for pointer types. * Also, check optionality for these types. */ #ifdef DYNAMIC_ARRAYS if ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR (melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F')) { U8 *deref_pstruct; /* Get pointer value */ deref_pstruct = *(U8 **)(globs->pstruct + globs->pstructOffs); /* * Strictly speaking the 'D' to 'F' types should not need this * check (should have returned after the optionality check above), * but it will catch stray NULL pointers (or uninitialized * valid flags) */ if (ccd_check_pointer(deref_pstruct) != ccdOK) { ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) e_ref, &globs->pstruct[globs->pstructOffs]); return; } /* * Pointer not NULL; * 1. Save old globs->pstruct and assign pointer to globs->pstruct * as new base. * 2. Set pstructOffs to 0 (zero) as the next offset will start * in the new memory area. */ old_pstruct = globs->pstruct; globs->pstruct = deref_pstruct; globs->pstructOffs = 0; } #endif /* * 20010621 MVJ: Dynamic array addition. * Types 'R' and 'F' point to base types (just as type 'V') and * read sizes from the same table. */ cSize = (ULONG)((melem[e_ref].elemType EQ 'V' #ifdef DYNAMIC_ARRAYS OR melem[e_ref].elemType EQ 'R' OR melem[e_ref].elemType EQ 'F' #endif ) ? mvar[melem[e_ref].elemRef].cSize : mcomp[melem[e_ref].elemRef].cSize ); startOffset = globs->pstructOffs; } else { repeat = (ULONG)((melem[e_ref].repType EQ 'c') ? melem[e_ref].maxRepeat : 1); multAppear = FALSE; cSize = 0; } if (multAppear AND lenT) { /* * multiple appearance of the repeated element is coded as * TLV0 TLV1 TLV2 .... */ t_repeat = repeat; v_repeat = 1; } else { t_repeat = 1; v_repeat = repeat; } /* * single appearance of the repeated element is coded as * TLV0V1V2V3 .... */ for (i=0; i < t_repeat; i++) { if (lenT) { /* * encode the T-component */ bf_codeByteNumber (lenT, (UBYTE) melem[e_ref].ident, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "encoding %d bits T-value (%x)", lenT, melem[e_ref].ident); #endif } /* * if lenL > 0 remember the position of the L-component, because * we know it after encoding the entire element. for GSM5TLV elements * it could be necessary to use 2 bytes for the length information. */ if (lenL) { posL = (ULONG) globs->bitpos; bf_incBitpos (lenL, globs); #ifdef DEBUG_CCD TRACE_CCD (globs, "skipping %d bits for L-value at byte %d.%d", lenL, globs->bytepos, globs->byteoffs); #endif } if (cSize) { /* * calculate the offset if it is not a spare */ globs->pstructOffs = (ULONG)(startOffset + (i * cSize)); } /* * Encode the value. Keep caution with BER encoding of ASN1 integers. * All other types can be encoded by a generic function. */ if (melem[e_ref].codingType EQ CCDTYPE_GSM1_ASN AND melem[e_ref].elemType EQ 'V' AND melem[e_ref].repType EQ ' ' ) { #ifdef DEBUG_CCD #ifdef CCD_SYMBOLS TRACE_CCD (globs, "BER encoding of ASN.1 integer %s", ccddata_get_alias((USHORT) e_ref, 1)); #else TRACE_CCD (globs, "BER encoding of ASN.1 integer; e_ref= %d", melem[e_ref].elemRef); #endif #endif switch (mvar[melem[e_ref].elemRef].cType) { case 'B': bf_writeBits (8, globs); break; case 'S': { if (*(U16 *) (globs->pstruct+globs->pstructOffs) <= (U16)0xFF) bf_writeBits (8, globs); else bf_writeBits (16, globs); } break; case 'L': { U32 tmpVal= *(U32 *) (globs->pstruct+globs->pstructOffs); if ( tmpVal <= (U32)0xFF) bf_writeBits (8, globs); else if ( tmpVal <= (U32)0xFFFF) bf_writeBits (16, globs); else if ( tmpVal <= (U32)0xFFFFFF) bf_writeBits (24, globs); else bf_writeBits (32, globs); } break; case 'X': { U16 ValLen= *(U16 *) (globs->pstruct+globs->pstructOffs); if ( mvar[melem[e_ref].elemRef].bSize >= ValLen) bf_writeBitChunk (ValLen, globs); else { #ifdef DEBUG_CCD TRACE_CCD (globs, "value length (%d) exceeds defined bSize!", ValLen); #endif } } break; } } else { cdc_encodeElemvalue (e_ref, v_repeat, globs); } /* * calculate the bitlen if it is an TLV element and write the * L-value. */ if (lenL) { switch (melem[e_ref].codingType) { case CCDTYPE_GSM5_TLV: { USHORT L = (((USHORT)((globs->bitpos - posL)-lenL)+7) >> 3); #ifdef DEBUG_CCD TRACE_CCD (globs, "recoding the 8 bit L-value (%d)", L); #endif if (L > 127) { /* * if the length is > 127 we code the first byte to * 0x81, shift the whole stuff rightwise by 8 and * encode the length in the next byte (16 bits for L) */ bf_rShift8Bit ((USHORT) (posL+8), (USHORT) (L<<3), globs); bf_incBitpos (8, globs); bf_recodeByteNumber ((USHORT) posL, lenL, (UBYTE) 0x81, globs); bf_recodeByteNumber ((USHORT) (posL+8), lenL, (UBYTE) L, globs); /* * set the bitpos to a 8 bit aligned position * corresponding the L value */ bf_setBitpos (posL+(L*8)+16, globs); } else { bf_recodeByteNumber ((USHORT) posL, lenL, (UBYTE) L, globs); /* * set the bitpos to a 8 bit aligned position * corresponding the L value */ bf_setBitpos (posL+(L*8)+8, globs); } break; } case CCDTYPE_GSM6_TLV: { USHORT L = ((USHORT)(((globs->bitpos - posL)-lenL)+7) >> 3); #ifdef DEBUG_CCD TRACE_CCD (globs, "recoding the 16 bit L-value (%d)", L); #endif bf_recodeShortNumber ((USHORT)posL, lenL, L, globs); /* * set the bitpos to a 8 bit aligned position * corresponding the L value */ bf_setBitpos (posL+(L*8)+16, globs); break; } case CCDTYPE_GSM7_LV: { USHORT L = (USHORT) ((globs->bitpos - posL)-lenL); #ifdef DEBUG_CCD TRACE_CCD (globs, "recoding the 7 bit L-value (bitlength) (%d)", L); #endif bf_recodeShortNumber ((USHORT)posL, lenL, L, globs); bf_setBitpos (posL+L+7, globs); break; } default: { USHORT L = ((USHORT)(((globs->bitpos - posL)-lenL)+7) >> 3); #ifdef DEBUG_CCD TRACE_CCD (globs, "recoding the 8 bit L-value (%d)", L); #endif bf_recodeByteNumber ((USHORT)posL, lenL, (UBYTE) L, globs); /* * Set the bitpos to a 8 bit aligned position * corresponding the L value */ bf_setBitpos (posL+(L*8)+8, globs); break; } } } } /* * Restore globs->pstruct if overwritten by pointer dereference. */ if (old_pstruct) globs->pstruct = old_pstruct; } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_GSM_start | +--------------------------------------------------------------------+ PURPOSE : Initialize the GSM specific codec part for each msg. */ void cdc_GSM_start (T_CCD_Globs *globs) { globs->Swap1V_inProgress = FALSE; globs->last_level = 255; cdc_init_ctx_table (globs); } #endif /* !RUN_FLASH */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : cdc_isPresent | +--------------------------------------------------------------------+ PURPOSE : For optional elements check the valid-flag in the C-struct. Spare elements in PER do not have a corresponding valid flag. In case of Dynamic Arrays: Postpone optional check for non-code transparent pointer types ('P', 'Q', 'R'). For these types, the optional flag is the pointer itself. These types cannot be checked yet, as the pointer may be preceeded by a counter octet, a union tag id octet etc. */ U16 cdc_isPresent (const ULONG e_ref, T_CCD_Globs *globs) { if (melem[e_ref].optional) { #ifdef DYNAMIC_ARRAYS if (melem[e_ref].elemType < 'P' OR melem[e_ref].elemType > 'R') { if(globs->pstruct[globs->pstructOffs++] == FALSE) return FALSE; #ifdef DEBUG_CCD else if (globs->pstruct [melem[e_ref].structOffs] != TRUE) { TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d", e_ref); } #endif } else { /*If elemType is P, Q or R - check the pointer value*/ if(*(void**) &globs->pstruct[globs->pstructOffs] == NULL) return FALSE; } #else if (globs->pstruct[globs->pstructOffs++] == FALSE) return FALSE; #ifdef DEBUG_CCD else if (globs->pstruct [melem[e_ref].structOffs] != TRUE) { TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d", e_ref); } #endif #endif } return TRUE; } #endif /* !RUN_INT_RAM */ #ifndef RUN_FLASH /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : is_pointer_type | +--------------------------------------------------------------------+ PURPOSE : Return TRUE for pointer elements. */ BOOL is_pointer_type (const ULONG e_ref) { return ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR (melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F')); } #endif /* !RUN_FLASH */ #ifndef RUN_FLASH /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : is_variable_type | +--------------------------------------------------------------------+ PURPOSE : Return TRUE for elements with variable character. */ BOOL is_variable_type (const ULONG e_ref) { return ((melem[e_ref].elemType == 'F') || ( melem[e_ref].elemType == 'R') || (melem[e_ref].elemType == 'V')); } #endif /* !RUN_FLASH */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : PER_CommonBegin | +--------------------------------------------------------------------+ PURPOSE : Common settings done by most of the encoding or decoding functions for UNALIGNED PER (UMTS). It handles position of pointer to the C-structure, valid flag for optional elements and length determinant for array of elements. */ SHORT PER_CommonBegin (const ULONG e_ref, ULONG *max_rep, T_CCD_Globs *globs) { /* * Set the offset in the C-structure on the value for this element */ globs->pstructOffs = melem[e_ref].structOffs; /* For optional elements we have already set the valid flag in the * C-structure while processing ASN1_SEQ. */ if ( ! cdc_isPresent(e_ref, globs) ) return (SHORT)ccdError; switch (melem[e_ref].repType) { case ' ': /* * Element is not an array. */ *max_rep = 1; break; case 'c': case 'C': /* * Read the size for an array of fixed length. */ *max_rep = (ULONG) melem[e_ref].maxRepeat; break; case 'j': case 'J': { /* * Read the size for an array of variable length. * Read the value of the last encoded element. It is the length * indicator. * Hint 1: globs->pstruct[melem[e_ref-1].structOffs is 0, since * fields of variable length are projected on a COMP made of an * ASN1_INTEGER for the lenght indicator and the field elements * (sequences, integers, octets or bits). * Hint 2: The current version of UMTS does not use length * indicators larger than 64K. Hence the use of USHORT for repeat. */ switch (mvar[melem[e_ref-1].elemRef].cType) { case 'B': *max_rep = (ULONG) globs->pstruct[melem[e_ref-1].structOffs]; break; case 'S': *max_rep = (ULONG) *(USHORT *) (globs->pstruct+melem[e_ref-1].structOffs); break; default: *max_rep = 0; break; } break; } default: ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); break; } /* * There is nothing to be encoded. */ if (*max_rep EQ 0) { return (SHORT)ccdError; } /* * Check the validity of the lenght information. */ else if (melem[e_ref].maxRepeat AND *max_rep > melem[e_ref].maxRepeat) { ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs); } return (SHORT)ccdOK; } #endif /* !RUN_INT_RAM */ #ifdef DYNAMIC_ARRAYS #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : PER_allocmem | +--------------------------------------------------------------------+ PURPOSE : Allocate memory for pointer types (dynamic array addition) Returns address of freshly allocated memory or ccdError in case no memory is available. */ U8 *PER_allocmem(const ULONG e_ref, ULONG repeat, T_CCD_Globs *globs) { /* * Check for pointer types; allocate memory if necessary. */ if ( is_pointer_type(e_ref) ) { ULONG cSize; U8 *addr; /* * Find size to allocate. * Read from mcomp or mvar according to type. */ cSize = (ULONG)((melem[e_ref].elemType EQ 'V' OR melem[e_ref].elemType EQ 'R' OR melem[e_ref].elemType EQ 'F') ? mvar[melem[e_ref].elemRef].cSize : mcomp[melem[e_ref].elemRef].cSize ); #ifdef DEBUG_CCD TRACE_CCD (globs, "PER_allocmem(): alloc%5d x%5d bytes (type '%c'); " "elem%5d ('%s')", repeat, cSize, melem[e_ref].elemType, e_ref, #ifdef CCD_SYMBOLS mcomp[melem[e_ref].elemRef].name #else "" #endif ); #endif /* * Allocate additional memory - append to existing mem chain */ cSize *= repeat; addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS); /* If no memory, log error and return immediately */ if (addr EQ NULL) { ccd_setError (globs, ERR_NO_MEM, BREAK, (USHORT) -1); return (U8 *)ccdError; } else memset (addr, 0, (size_t)cSize); return addr; } return (U8 *)ccdError; } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : PER_allocmem_and_update| +--------------------------------------------------------------------+ PURPOSE : Allocate memory for pointer types (dynamic array addition) Updates global variables after allocation (globs->pstruct and globs->pstructOffs). Assumes that these global variables are saved by the calling function. Returns ccdOK or ccdError in case no memory is available. */ USHORT PER_allocmem_and_update(const ULONG e_ref, ULONG repeat, T_CCD_Globs *globs) { U8 *addr; /* Allocate memory */ addr = PER_allocmem(e_ref, repeat, globs); /* No memory ? */ if ( addr != (U8 *)ccdError ) { /* * Memory allocated; * 1. Store pointer to freshly allocated memory area in structure * 2. Initialize pstruct to point to the freshly allocated memory area. * 3. Initialize pstructOffs to 0 to start decoding at offset 0 * in the new memory area. * Assumes that globs->pstruct is saved in the calling function. */ *(U8 **)(globs->pstruct + globs->pstructOffs) = addr; globs->pstruct = addr; globs->pstructOffs = 0; return ccdOK; } else { /* No memory - Return error */ return ccdError; } } #endif /* !RUN_INT_RAM */ #endif #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : Read_NormallySmallNonNegativeWholeNr| +--------------------------------------------------------------------+ PURPOSE : Read a normally small non-negative whole number as defined by ASN.1 PER. Function is used to read elements such as: a) bit-map field of SEQUENCE extensions, b) index of CHOICE extension or c) extension value of extensible INTEGER or ENUMERATED. */ U32 Read_NormallySmallNonNegativeWholeNr (T_CCD_Globs *globs) { U32 value_length=0; /* Read the first bit. If set to 0 it means the value is encoded * in the following five bits. Else read a normally small ...nr. */ if (bf_readBit (globs) EQ 0) { return ((U32) bf_getBits (6, globs)); } else { /* * Do not handle the theoretical case that value length * needs more than 63 bits. */ bf_incBitpos (1, globs); /* * Read the value length first. * Then use the length to read the value. */ value_length = (U32) bf_getBits (6, globs); return ((U32) bf_getBits (value_length, globs)); } } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : Write_NormallySmallNonNegativeWholeNr| +--------------------------------------------------------------------+ PURPOSE : Write a normally small non-negative whole number as defined by ASN.1 PER. Function is used to encode elements such as: a) bit-map field of SEQUENCE extensions, b) index of CHOICE extension or c) extension value of extensible INTEGER or ENUMERATED. */ void Write_NormallySmallNonNegativeWholeNr (U32 Value, T_CCD_Globs *globs) { /* For small numbers write 0 in the first bit. * Then encode that number in the succeeding five bits. */ if (Value < 64) { bf_writeBit (0, globs); bf_writeVal (Value, 6, globs); } /* * Encode the number under the assumption that its length is * given by less than 63 bits. Hence encode also the length as a * normally small... */ else { /* Set flag bits: * 1 means "length determinant encoded before the value itself" * 0 means "length determinant encoded only in five bits" */ bf_writeVal (2, 2, globs); bf_writeVal (bitSize[Value], 5, globs); /* Encode the number itself */ bf_writeVal (Value, bitSize[Value], globs); } return; } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : Read_OpenTpye_Length | +--------------------------------------------------------------------+ PURPOSE : Read length of an ASN.1 open type. Open types are normally found in encoding of parametrized information objects and extension types. */ U32 Read_OpenTpye_Length (T_CCD_Globs *globs) { U32 Value; /* * Flag bit is 0 for "Value < 128" which means * "encoding fits in the current octet" */ if (bf_readBit (globs) EQ 0) { Value = bf_getBits (7, globs); } /* * Flag bits are 10 for 128 "< Value < 16K". * 1 means "encoding does not fit in the current octet". * 0 means "encoding needs only one further octet". */ else if (bf_readBit (globs) EQ 0) { Value = bf_getBits (14, globs); } /* Currently no support for bigger values is required. */ else { /* force error detection */ Value = 0; } return Value; } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_COM | | STATE : code ROUTINE : Write_OpenTpye_Length | +--------------------------------------------------------------------+ PURPOSE : Write length of an ASN.1 open type. Open types are normally found in encoding of parametrized information objects and extension types. */ void Write_OpenTpye_Length (U32 Value, T_CCD_Globs *globs) { if (Value < 128) { bf_writeVal (Value, 8, globs); } else if (Value < 0x8000) { /* Set flag bits: * 1 means "encoding does not fit in the current octet" * 0 means "encoding needs only one further octet" */ bf_writeVal (2, 2, globs); bf_writeVal (Value, 14, globs); } /* Currently no support for bigger values is required. */ else {} return; } #endif /* !RUN_INT_RAM */