FreeCalypso > hg > fc-tourmaline
view src/gpf/ccd/Ccdedit.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 : Ccdedit.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 : Coder Decoder editfunctions for reading/writing the | C-Structures of primitives and messages. +----------------------------------------------------------------------------- */ #define CCDEDIT_C #include <stdio.h> #include <stdlib.h> #include <string.h> /* * standard definitions like UCHAR, ERROR etc. */ #include "typedefs.h" /* * Declaration of coder/decoder-tables */ #include "ccdtable.h" #include "ccddata.h" #include "ccdedit.h" typedef union { UBYTE buffer[4]; UBYTE b[4]; USHORT s[2]; ULONG l; } T_CONV; typedef enum { isvar, isstruct, isunion, issdu, isductrl } T_ELEMTYPE; /* * strncpy() does not append a null chararcter to the copied string; * This macro adds a terminating null following a call to strncpy() * In Ccdedit.h the buffers are all len+1 bytes long. */ #define STRNCPY(dest,source,len) {\ strncpy (dest, source, len);\ dest [len] = 0;\ } static const T_CCD_CompTabEntry* mcomp; static const T_CCD_CompTabEntry* pcomp; static const T_CCD_VarTabEntry* pvar; static const T_CCD_ElemTabEntry* pelem; static const T_CCD_StrTabEntry* pstr; static const T_CCD_VarTabEntry* mvar; static const T_CCD_ElemTabEntry* melem; static const T_CCD_StrTabEntry* mstr; static const T_CCD_ValTabEntry* mval; static const T_CCD_ValTabEntry* pval; static int ccddata_num_of_entities; static int ccddata_max_message_id; static int ccddata_max_primitive_id; static int ccddata_max_sap_num; void CCDDATA_PREF(cde_init) () { mcomp = ccddata_get_mcomp (0); pcomp = ccddata_get_pcomp (0); pvar = ccddata_get_pvar (0); pelem = ccddata_get_pelem (0); pstr = ccddata_get_pstr (0); mvar = ccddata_get_mvar (0); melem = ccddata_get_melem (0); mstr = ccddata_get_mstr (0); mval = ccddata_get_mval (0); pval = ccddata_get_pval (0); ccddata_num_of_entities = ccddata_get_num_of_entities (); ccddata_max_message_id = ccddata_get_max_message_id (); ccddata_max_primitive_id = ccddata_get_max_primitive_id (); ccddata_max_sap_num = ccddata_get_max_sap_num (); } /* +------------------------------------------------------------------------------ | Function : cde_val_iterate +------------------------------------------------------------------------------ | Description : This function searches the values in [pm]val.cdg for | a given value and depending on the value of the parameter | 'copy' adds the "Comment" of the SAP-/MSG-catalogues | to the member symbolicValue of a given T_CCDE_ELEM_DESCR. | | Parameters : elem_value - the actual value searched for | edescr - the element descriptor | copy - s.a. | | Return : -1 if no values are defined or if the value is not found; | else: the ordinal of the value in relation to first valid | value of the var +------------------------------------------------------------------------------ */ static void cde_val_iterate (int elem_value, T_CCDE_ELEM_DESCR* edescr) { S32 StartVal, EndVal; BOOL IsDefault; char *ValStr; SHORT NumDefs; USHORT ValueDef; USHORT valdefstart; const T_CCD_ValTabEntry* val; const T_CCD_StrTabEntry* str; if (edescr->ccdIndex == NO_REF) return; if (edescr->esource EQ FromMsg) { NumDefs = mvar[edescr->ccdIndex].numValueDefs; ValueDef = mvar[edescr->ccdIndex].valueDefs; val = mval; str = mstr; } else { NumDefs = pvar[edescr->ccdIndex].numValueDefs; ValueDef = pvar[edescr->ccdIndex].valueDefs; val = pval; str = pstr; } valdefstart = ValueDef; edescr->valcheck = NumDefs ? -1 : 1; while (NumDefs-- > 0) { IsDefault = val[ValueDef].isDefault; ValStr = str[val[ValueDef].valStringRef]; StartVal = val[ValueDef].startValue; EndVal = val[ValueDef].endValue; if (IsDefault) { /* default definition */ STRNCPY (edescr->symbolicValue, ValStr, SYMBOLIC_VAL_LENGTH); /* * If IsDefault is 2 it is an ASN1 default value; StartVal and EndVal * are set to the value. If IsDefault is 1, it means only a default * symbolic value, but StartVal and EndVal are not set. In this case * valcheck get the value 0. */ if (IsDefault == 2) { if (elem_value == StartVal) { edescr->valcheck = 1; return; } } else { edescr->valcheck = 0; } } else { if (elem_value == StartVal && elem_value == EndVal) { STRNCPY (edescr->symbolicValue, ValStr, SYMBOLIC_VAL_LENGTH); edescr->valcheck = 1; return; } if (elem_value >= StartVal AND elem_value <= EndVal) { /* found in range, but continue to search an exact match */ STRNCPY (edescr->symbolicValue, ValStr, SYMBOLIC_VAL_LENGTH); edescr->valcheck = 1; } } ValueDef++; } } static void eval_elemtype (T_CCDE_ELEM_DESCR* edescr, const T_CCD_ElemTabEntry* elem, T_ELEMTYPE* elemtype, BOOL* linked) { *linked = FALSE; switch (elem->elemType) { case 'W': case 'M': case 'I': *linked = TRUE; /* fallthrough */ case 'V': case 'R': case 'F': *elemtype = isvar; break; case 'Z': case 'K': case 'G': *linked = TRUE; /* fallthrough */ case 'C': case 'P': case 'D': *elemtype = isstruct; break; case 'c': case 'p': case 'd': *elemtype = issdu; break; case 'Y': case 'L': case 'H': *linked = TRUE; /* fallthrough */ case 'U': case 'Q': case 'E': *elemtype = isunion; break; case '!': *elemtype = isductrl; break; } if ((elem->elemType >= 'P' && elem->elemType <= 'R') || (elem->elemType >= 'K' && elem->elemType <= 'M') || elem->elemType == 'p') edescr->ptrtype = usptr; else if((elem->elemType >= 'D' && elem->elemType <= 'F') || (elem->elemType >= 'G' && elem->elemType <= 'I') || elem->elemType == 'd') edescr->ptrtype = ctptr; else edescr->ptrtype = noptr; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_get_next_elem | +--------------------------------------------------------------------+ PURPOSE : */ static USHORT cde_get_next_elem (T_CCDE_HANDLE *handle, UBYTE descent, T_CCDE_ELEM_DESCR *edescr) { T_CCDE_CONTEXT * ctx; BOOL isMsg; BOOL linked; BOOL validElemFound = FALSE; const T_CCD_VarTabEntry *var; const T_CCD_CompTabEntry *comp; const T_CCD_ElemTabEntry *elem; const T_CCD_StrTabEntry *str; T_ELEMTYPE elemtype; isMsg = handle->source == FromMsg; if (isMsg) /* var, str, and comp may become reset later */ { comp = mcomp; elem = melem; str = mstr; var = mvar; } else { comp = pcomp; elem = pelem; str = pstr; var = pvar; } if (descent > handle->level AND handle->canDescent) handle->level++; handle->canDescent = FALSE; ctx = &handle->context[handle->level]; do { if (ctx->numElems EQ 0) { /* * end of composition or maybe of the entire message/primitive. */ if (handle->level > 0) { /* * end of substructured element. * switch to the context of the previous level. */ handle->level--; ctx = &handle->context[handle->level]; } else { edescr->offset = comp[ctx->structIdx].cSize + handle->lenVarPart; return isMsg ? CCDEDIT_END_OF_MSG : CCDEDIT_END_OF_PRIM; } } /* * skip the spare elements (do it only for messages) */ if (ctx->numElems) { /* * remember: primitives does not contain spare definitions */ if (elem[ctx->elemIdx].elemType == 'S') { ctx->elemIdx++; ctx->numElems--; } else validElemFound = TRUE; } } while (!validElemFound); eval_elemtype (edescr, &elem[ctx->elemIdx], &elemtype, &linked); if (elemtype == isductrl) { edescr->btype = T_ductrl; ctx->elemIdx++; ctx->numElems--; return CCDEDIT_OK; } if (linked) { /* element linked from pelem to mvar/mcomp */ edescr->esource = FromMsg; comp = mcomp; var = mvar; str = mstr; } else edescr->esource = handle->source; if (ctx->state EQ TRAVERSE_ARRAY) { /* * for every array element calculate the offset for the * C-structure access. * offset = leveloffset + (arrayIndex * csize) + 1 */ edescr->offset = elem[ctx->elemIdx].structOffs + ctx->levelOffset + (ctx->arrayIndex * ((elem[ctx->elemIdx].elemType NEQ 'C') ? var[elem[ctx->elemIdx].elemRef].cSize : comp[elem[ctx->elemIdx].elemRef].cSize ) ); /* + 1; */ } else { edescr->offset = elem[ctx->elemIdx].structOffs + ctx->levelOffset; } edescr->level = handle->level; edescr->maxRepeat = elem[ctx->elemIdx].maxRepeat; edescr->index = NO_REF; edescr->ccdIndex = NO_REF; edescr->validRepeats = NO_REF; edescr->isOptional = elem[ctx->elemIdx].optional; edescr->arrayType = NoArray; edescr->elemref = NO_REF; edescr->u_member = FALSE; edescr->u_ctrl = 0xffffffff; edescr->bitstring = 0; edescr->c_implicit = 1; edescr->issigned = 0; edescr->valcheck = 0; if ( edescr->maxRepeat > 0 && elem[ctx->elemIdx].repType != 'b' && elem[ctx->elemIdx].repType != 's' && elem[ctx->elemIdx].elemType != 'E' && ctx->state == TRAVERSE_STRUCTURE) { edescr->arrayType = ( elem[ctx->elemIdx].repType == 'v' || elem[ctx->elemIdx].repType == 'i' || elem[ctx->elemIdx].repType == 'J' || elem[ctx->elemIdx].repType == 'j') ? VarArray : FixArray; if (elem[ctx->elemIdx].repType == 'C' || elem[ctx->elemIdx].repType == 'J') edescr->bitstring = 1; if (elem[ctx->elemIdx].repType == 'j' || elem[ctx->elemIdx].repType == 'J') edescr->c_implicit = 0; if (handle->level < MAX_LEVELS) { T_CCDE_CONTEXT * new_ctx = ctx+1; ctx->repeats = edescr->maxRepeat; handle->canDescent = TRUE; new_ctx->structIdx = ctx->structIdx; new_ctx->elemIdx = ctx->elemIdx; new_ctx->elemType = 0; new_ctx->arrayIndex = 0; new_ctx->numElems = edescr->maxRepeat; new_ctx->levelOffset = ctx->levelOffset; new_ctx->arrayType = edescr->arrayType; new_ctx->state = TRAVERSE_ARRAY; /* * if the composition is optional, increment the offset * because of the valid flag (v_xxx). */ if (edescr->isOptional) new_ctx->levelOffset++; /* * if the composition is a array with variable size, * increment the offset because of the counter (c_xxx). */ if (edescr->arrayType EQ VarArray) new_ctx->levelOffset += edescr->maxRepeat >> 8 ? 2 : 1; } } if (ctx->state EQ TRAVERSE_ARRAY) { /* * if the size of the array is variable, mark the * components of this array as optional. So we can later * determine if the array component is valid */ if (ctx->arrayType EQ VarArray) edescr->isOptional = TRUE; /* * increment the array index */ edescr->index = ctx->arrayIndex++; } if (elemtype == isvar) { /* * basic element (var) */ switch (var[elem[ctx->elemIdx].elemRef].cType) { case 'C': edescr->issigned = 1; /* fallthrough */ case 'B': edescr->btype = T_byte; break; case 'T': edescr->issigned = 1; /* fallthrough */ case 'S': edescr->btype = T_short; break; case 'M': edescr->issigned = 1; /* fallthrough */ case 'L': edescr->btype = T_long; break; case 'X': edescr->btype = T_buffer; break; } edescr->bytelen = var[elem[ctx->elemIdx].elemRef].cSize; #ifdef CCD_SYMBOLS strcpy (edescr->aname, var[elem[ctx->elemIdx].elemRef].name); strcpy (edescr->sname, ccddata_get_alias (ctx->elemIdx, (int) isMsg)); if (edescr->sname[0] == '\0') strcpy (edescr->sname, var[elem[ctx->elemIdx].elemRef].name); STRNCPY (edescr->lname, str[var[elem[ctx->elemIdx].elemRef].longNameRef], LONG_NAME_LENGTH); #else strcpy (edescr->sname, "No name info avail."); strcpy (edescr->aname, "No name info avail."); strcpy (edescr->lname, "No name info avail."); #endif } else if (elemtype == isunion) { /* union */ edescr->btype = T_union; edescr->bytelen = comp[elem[ctx->elemIdx].elemRef].cSize; edescr->elemref = elem[ctx->elemIdx].elemRef; #ifdef CCD_SYMBOLS strcpy (edescr->aname, comp[elem[ctx->elemIdx].elemRef].name); strcpy (edescr->sname, ccddata_get_alias (ctx->elemIdx, (int) isMsg)); if (edescr->sname[0] == '\0') strcpy (edescr->sname, comp[elem[ctx->elemIdx].elemRef].name); STRNCPY (edescr->lname, str[comp[elem[ctx->elemIdx].elemRef].longNameRef], LONG_NAME_LENGTH); #else strcpy (edescr->sname, "No name info avail."); strcpy (edescr->aname, "No name info avail."); strcpy (edescr->lname, "No name info avail."); #endif } else { /* * substructured info element */ if (elemtype == issdu) edescr->btype = T_issdu; else edescr->btype = T_struct; edescr->bytelen = comp[elem[ctx->elemIdx].elemRef].cSize; edescr->elemref = elem[ctx->elemIdx].elemRef; #ifdef CCD_SYMBOLS strcpy (edescr->aname, comp[elem[ctx->elemIdx].elemRef].name); strcpy (edescr->sname, ccddata_get_alias (ctx->elemIdx, (int) isMsg)); if (edescr->sname[0] == '\0') strcpy (edescr->sname, comp[elem[ctx->elemIdx].elemRef].name); STRNCPY (edescr->lname, str[comp[elem[ctx->elemIdx].elemRef].longNameRef], LONG_NAME_LENGTH); #else strcpy (edescr->sname, "No name info avail."); strcpy (edescr->aname, "No name info avail."); strcpy (edescr->lname, "No name info avail."); #endif if (edescr->arrayType EQ NoArray AND handle->level < MAX_LEVELS) { T_CCDE_CONTEXT * new_ctx = ctx+1; handle->canDescent = TRUE; new_ctx->structIdx = elem[ctx->elemIdx].elemRef; new_ctx->elemIdx = comp[new_ctx->structIdx].componentRef; new_ctx->elemType = 0; new_ctx->arrayIndex = 0; new_ctx->numElems = comp[new_ctx->structIdx].numOfComponents; new_ctx->levelOffset = edescr->offset; /* * if the composition is optional, increment the offset * because of the valid flag (v_xxx). */ if (edescr->isOptional) new_ctx->levelOffset++; /* * if the composition is a array with variable size, * increment the offset because of the counter (c_xxx). */ if (edescr->arrayType EQ VarArray) new_ctx->levelOffset++; new_ctx->state = TRAVERSE_STRUCTURE; } } if (edescr->arrayType EQ NoArray && elem[ctx->elemIdx].elemType == 'V' AND var[elem[ctx->elemIdx].elemRef].numValueDefs > 0) { /* * value definitions available * store the index of this information element in the * element descriptor for later value requests. */ edescr->ccdIndex = elem[ctx->elemIdx].elemRef; } ctx->numElems--; if (ctx->state EQ TRAVERSE_STRUCTURE) ctx->elemIdx++; return CCDEDIT_OK; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_prim_first | +--------------------------------------------------------------------+ PURPOSE : */ USHORT CCDDATA_PREF(cde_prim_first) (T_CCDE_HANDLE * phandle, ULONG primcode, char * name) { USHORT SAP, Opcode, Direction, ThePrimitive; if (primcode & 0x80000000) { SAP = (USHORT) (primcode & 0x3fff); Opcode = (USHORT) ((primcode >> 16) & 0xff); } else { SAP = (USHORT) (((primcode & 0x3f00)>>8) & 0xff); Opcode = (USHORT) (primcode & 0xff); } Direction = (USHORT) (((primcode & 0x4000)>>14) & 0x01); if (SAP > ccddata_max_sap_num OR Opcode > ccddata_max_primitive_id) return CCDEDIT_PRIM_NOT_FOUND; if ((ThePrimitive = ccddata_get_pmtx(SAP,Opcode,Direction)) EQ NO_REF) return CCDEDIT_PRIM_NOT_FOUND; phandle->context[0].structIdx = ThePrimitive; #ifdef CCD_SYMBOLS strcpy (name, pcomp[phandle->context[0].structIdx].name); #else strcpy (name, "No name info avail."); #endif phandle->level = 0; phandle->context[0].elemIdx = pcomp[phandle->context[0].structIdx].componentRef; phandle->context[0].elemType = 0; phandle->context[0].numElems = pcomp[phandle->context[0].structIdx].numOfComponents; phandle->context[0].levelOffset = 0; phandle->context[0].arrayIndex = 0; phandle->context[0].state = TRAVERSE_STRUCTURE; phandle->canDescent = FALSE; phandle->source = FromPrim; phandle->maxCSize = pcomp[phandle->context[0].structIdx].cSize; phandle->lenVarPart = 0; return CCDEDIT_OK; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_prim_next | +--------------------------------------------------------------------+ PURPOSE : */ USHORT CCDDATA_PREF(cde_prim_next) (T_CCDE_HANDLE *phandle, UBYTE descent, T_CCDE_ELEM_DESCR *pdescr) { return cde_get_next_elem (phandle, descent, pdescr); } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_msg_first | +--------------------------------------------------------------------+ PURPOSE : */ USHORT CCDDATA_PREF(cde_msg_first) (T_CCDE_HANDLE * mhandle, UBYTE type, UBYTE direction, UBYTE entity, char * name) { USHORT TheMessage; if (entity > ccddata_num_of_entities OR type > ccddata_max_message_id) return CCDEDIT_MESSAGE_NOT_FOUND; if ((TheMessage = ccddata_get_mmtx((USHORT) entity, (USHORT) type, (USHORT) direction)) EQ NO_REF) return CCDEDIT_MESSAGE_NOT_FOUND; mhandle->context[0].structIdx = TheMessage; #ifdef CCD_SYMBOLS strcpy (name, mcomp[mhandle->context[0].structIdx].name); #else strcpy (name, "No name info avail."); #endif mhandle->level = 0; mhandle->context[0].elemIdx = mcomp[mhandle->context[0].structIdx].componentRef; mhandle->context[0].elemType = 0; mhandle->context[0].numElems = mcomp[mhandle->context[0].structIdx].numOfComponents; mhandle->context[0].levelOffset = 0; mhandle->context[0].arrayIndex = 0; mhandle->context[0].state = TRAVERSE_STRUCTURE; mhandle->canDescent = FALSE; mhandle->source = FromMsg; mhandle->maxCSize = mcomp[mhandle->context[0].structIdx].cSize; mhandle->lenVarPart = 0; return CCDEDIT_OK; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_msg_next | +--------------------------------------------------------------------+ PURPOSE : */ USHORT CCDDATA_PREF(cde_msg_next) (T_CCDE_HANDLE *mhandle, UBYTE descent, T_CCDE_ELEM_DESCR *iedescr) { return cde_get_next_elem (mhandle, descent, iedescr); } /* +------------------------------------------------------------------------------ | Function : cde_get_comp +------------------------------------------------------------------------------ | Description : This function works with similar results like cde_comp_first, | but not the whole comp table is searched for the name of the | component. Instead the previous set elemref in the | parameter edescr is taken to directly jump to the component. | The component found is compared with the given name in | edescr. If equal chandle is defined. Otherwise there is an | error. | | Parameters : chandle - the handle for the component (returned) | edescr - the element descriptor | | Return : CCDEDIT_OK on success, CCDEDIT_COMP_NOT_FOUND otherwise +------------------------------------------------------------------------------ */ USHORT CCDDATA_PREF(cde_get_comp) (T_CCDE_HANDLE* chandle, T_CCDE_ELEM_DESCR* edescr) { const T_CCD_CompTabEntry* comp; USHORT index = edescr->elemref; if (index == NO_REF) return CCDEDIT_COMP_NOT_FOUND; comp = edescr->esource == FromMsg ? &mcomp[index] : &pcomp[index]; #ifdef CCD_SYMBOLS if (strcmp (comp->name, edescr->aname)) return CCDEDIT_COMP_NOT_FOUND; #endif /* CCD_SYMBOLS */ chandle->context[0].structIdx = index; chandle->level = 0; chandle->context[0].elemIdx = comp->componentRef; chandle->context[0].elemType = 0; chandle->context[0].numElems = comp->numOfComponents; chandle->context[0].levelOffset = 0; chandle->context[0].arrayIndex = 0; chandle->context[0].state = TRAVERSE_STRUCTURE; chandle->canDescent = FALSE; chandle->source = edescr->esource; chandle->maxCSize = comp->cSize; chandle->lenVarPart = 0; return CCDEDIT_OK; } /* +------------------------------------------------------------------------------ | Function : cde_comp_alias +------------------------------------------------------------------------------ | Description : This function works with similar results like cde_comp_first, | but not thewhole comp table is searched for the name of the | component. Instead the alias name (as_name) from ?elem.cdg | is taken for name comparison. | | Parameters : chandle - the handle for the component (returned) | source - if message or primitve | name - the name of the searched component | | Return : CCDEDIT_OK on success, CCDEDIT_COMP_NOT_FOUND otherwise +------------------------------------------------------------------------------ */ USHORT cde_comp_alias (T_CCDE_HANDLE * chandle, T_ELM_SRC source, char * name) { const T_CCD_CompTabEntry* comp; const T_CCD_ElemTabEntry* elem; int found = 0; USHORT index, cindex; elem = source == FromMsg ? melem : pelem; index = 0; while (!found AND (ccddata_get_alias (index, source == FromMsg) != NULL)) { /* name found */ if (elem[index].elemType == 'C' && !strcmp (ccddata_get_alias (index, source == FromMsg), name)) found = 1; else index++; } if (!found) return CCDEDIT_COMP_NOT_FOUND; cindex = elem[index].elemRef; comp = source == FromMsg ? &mcomp[cindex] : &pcomp[cindex]; chandle->context[0].structIdx = cindex; chandle->level = 0; chandle->context[0].elemIdx = comp->componentRef; chandle->context[0].elemType = 0; chandle->context[0].numElems = comp->numOfComponents; chandle->context[0].levelOffset = 0; chandle->context[0].arrayIndex = 0; chandle->context[0].state = TRAVERSE_STRUCTURE; chandle->canDescent = FALSE; chandle->source = source; chandle->maxCSize = comp->cSize; chandle->lenVarPart = 0; return CCDEDIT_OK; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_comp_first | +--------------------------------------------------------------------+ PURPOSE : */ USHORT CCDDATA_PREF(cde_comp_first) (T_CCDE_HANDLE * chandle, T_ELM_SRC source, char * compname) { USHORT index; BOOL found = FALSE; if (source EQ FromMsg) { /* * search the mcomp-table for the given name */ index = 0; while (!found AND mcomp[index].name NEQ NULL) { /* * composition name found */ if (strcmp (mcomp[index].name, compname) EQ 0) found = TRUE; else index++; } if (found) chandle->context[0].structIdx = index; else return CCDEDIT_COMP_NOT_FOUND; chandle->level = 0; chandle->context[0].elemIdx = mcomp[index].componentRef; chandle->context[0].elemType = 0; chandle->context[0].numElems = mcomp[index].numOfComponents; chandle->context[0].levelOffset = 0; chandle->context[0].arrayIndex = 0; chandle->context[0].state = TRAVERSE_STRUCTURE; chandle->canDescent = FALSE; chandle->source = FromMsg; chandle->maxCSize = mcomp[index].cSize; chandle->lenVarPart = 0; } else { /* * search the pcomp-table for the given name */ index = 0; while (!found AND pcomp[index].name NEQ NULL) { /* * composition name found */ if (strcmp (pcomp[index].name, compname) EQ 0) found = TRUE; else index++; } if (found) chandle->context[0].structIdx = index; else return CCDEDIT_COMP_NOT_FOUND; chandle->level = 0; chandle->context[0].elemIdx = pcomp[index].componentRef; chandle->context[0].elemType = 0; chandle->context[0].numElems = pcomp[index].numOfComponents; chandle->context[0].levelOffset = 0; chandle->context[0].arrayIndex = 0; chandle->context[0].state = TRAVERSE_STRUCTURE; chandle->canDescent = FALSE; chandle->source = FromPrim; chandle->maxCSize = pcomp[index].cSize; chandle->lenVarPart = 0; } return CCDEDIT_OK; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_comp_next | +--------------------------------------------------------------------+ PURPOSE : */ USHORT CCDDATA_PREF(cde_comp_next) (T_CCDE_HANDLE *chandle, UBYTE descent, T_CCDE_ELEM_DESCR *descr) { return cde_get_next_elem (chandle, descent, descr); } /* +------------------------------------------------------------------------------ | Function : cde_get_symval +------------------------------------------------------------------------------ | Description : This function adds the "Comment" of the SAP-/MSG-catalogues | to the member symbolicValue of a given T_CCDE_ELEM_DESCR. | | Parameters : elem_value - the actual value for that the comment | is searched for | edescr - the element descriptor | | Return : The string itself is returned which is a pointer to | '\0' if no comment was defined for that value. +------------------------------------------------------------------------------ */ char* CCDDATA_PREF(cde_get_symval) (int elem_value, T_CCDE_ELEM_DESCR* edescr) { edescr->symbolicValue[0] = '\0'; cde_val_iterate (elem_value, edescr); return edescr->symbolicValue; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_read_elem | +--------------------------------------------------------------------+ PURPOSE : Reads the value of the element, referenced by the element descriptor edescr, out of the C-Structure cstruct. The value is stored in the memory area, addressed by the parameter value. */ USHORT CCDDATA_PREF(cde_read_elem) (T_CCDE_HANDLE * handle, void * cstruct, T_CCDE_ELEM_DESCR * edescr, UBYTE * value) { T_CONV * cvp; U32 voffset; ULONG elem_value; UBYTE * cs = (UBYTE *) cstruct; /* * if this element is optional and it is no array component * read the valid flag out of the C-structure. */ if (edescr->isOptional && edescr->index == NO_REF && edescr->ptrtype != usptr) { voffset = edescr->offset++; edescr->isValid = (cs[voffset] EQ TRUE); } else { if (edescr->index NEQ NO_REF) { T_CCDE_CONTEXT *last_ctx; last_ctx = &handle->context[handle->level-1]; edescr->isValid = (edescr->index < last_ctx->repeats); } else edescr->isValid = TRUE; } if (!edescr->isValid) return CCDEDIT_OK; if (edescr->u_member) { edescr->u_ctrl = * (U32 *) &cs[edescr->offset]; edescr->offset += sizeof (U32); } if (edescr->arrayType NEQ NoArray) { T_CCDE_CONTEXT *ctx; ctx = &handle->context[handle->level]; /* * array of message elements (info elements) */ if (edescr->arrayType EQ VarArray) { USHORT sz_of_len; sz_of_len = edescr->maxRepeat >> 8 ? 2 : 1; /* 1 or 2 bytes for len */ if (sz_of_len == 1) { ctx->repeats = (USHORT) cs[edescr->offset]; } else { ctx->repeats = * (USHORT *) &cs[edescr->offset]; } edescr->offset += sz_of_len; if (ctx->repeats > edescr->maxRepeat) ctx->repeats = edescr->maxRepeat; } else ctx->repeats = edescr->maxRepeat; edescr->bytelen = edescr->bytelen * ctx->repeats; edescr->validRepeats = ctx->repeats; *value++ = (UBYTE) edescr->validRepeats; } if (edescr->ptrtype != noptr) { cs = * (UBYTE **) &cs[edescr->offset]; if (!cs) { edescr->isValid = FALSE; return CCDEDIT_OK; } } else cs += edescr->offset; /* * read the current value from the C-structure */ if ((edescr->btype == T_issdu) || (edescr->btype == T_buffer)) { USHORT l_buf, o_buf, len; /* * For the structure SDU perform a special handling. * The SDU contains l_buf and o_buf and the element * buf. This element is only defined as buf[1] because * the real length results of the encoded message and * must be calculated form l_buf and o_buf */ /* * read l_buf and o_buf (length and offset) out of the struct */ memcpy ((UBYTE *)&l_buf, cs, sizeof (USHORT)); memcpy ((UBYTE *)&o_buf, cs+sizeof (USHORT), sizeof (USHORT)); len = ((l_buf+o_buf+7)/8); handle->lenVarPart += len; handle->canDescent = FALSE; if ((edescr->btype == T_issdu) && ((len > (U32)(ccddata_get_max_bitstream_len()/8)) || (len > 0x1FFF))) /* max bytes: 0xFFFF/8 = 0x1FFF */ { return CCDEDIT_MESSAGE_ERROR; } edescr->bytelen = (2 * sizeof (USHORT)) + len; } memcpy (value, cs, edescr->bytelen); cvp = (T_CONV *) cs; switch (edescr->btype) { case T_byte: elem_value = (ULONG) cvp->b[0]; break; case T_short: elem_value = (ULONG) cvp->s[0]; break; case T_long: elem_value = (ULONG) cvp->l; break; default: return CCDEDIT_OK; } (void) CCDDATA_PREF(cde_get_symval) (elem_value, edescr); return CCDEDIT_OK; } /* +------------------------------------------------------------------------------ | Function : cde_write_prepare +------------------------------------------------------------------------------ | Description : This function prepares the writing of elements, by setting | valid flag, union controller and length of vaiable arrays | if necessary. Current version: only valid flag and union | controller. | | Parameters : same as cde_write_elem except value | | Return : - +------------------------------------------------------------------------------ */ void CCDDATA_PREF(cde_write_prepare) (T_CCDE_HANDLE * handle, void * cstruct, T_CCDE_ELEM_DESCR * edescr) { UBYTE * cs = (UBYTE *) cstruct; /* * if this element is optional and it is no array component * set the corresponding valid flag in the C-structure. */ if (edescr->isOptional && edescr->ptrtype != usptr) { cs[edescr->offset++] = TRUE; } if (edescr->u_member) { * (U32 *) &cs[edescr->offset] = (UBYTE) edescr->u_ctrl; edescr->offset += sizeof (U32); } } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_write_elem | +--------------------------------------------------------------------+ PURPOSE : Write the value wich is stored in the memory area, addressed by the parameter value, into the C-Structure element, referenced by the element descriptor edescr. */ USHORT CCDDATA_PREF(cde_write_elem) (T_CCDE_HANDLE * handle, void * cstruct, T_CCDE_ELEM_DESCR * edescr, UBYTE * value) { char *cs = (UBYTE *) cstruct; char *vb; U32 len; CCDDATA_PREF(cde_write_prepare) (handle, cs, edescr); if ((edescr->arrayType != NoArray) && (edescr->btype != T_struct)) { T_CCDE_CONTEXT *ctx; T_CCDE_CONTEXT _ctx; ctx = handle ? &handle->context[handle->level] : &_ctx; /* * Array of message elements (info elements) or * parameter. * In case of variable sized arrays, store the * amount of elements into the corresponding c_xxx variable */ if (edescr->arrayType EQ VarArray) { /* * array with a variable number of elements * set the c_xxx variable in the C-Structure */ USHORT sz_of_len; sz_of_len = edescr->maxRepeat >> 8 ? 2 : 1; /* 1 or 2 bytes for len */ if (sz_of_len == 1) { cs[edescr->offset] = (UBYTE) edescr->validRepeats; } else { * (USHORT *) &cs[edescr->offset] = edescr->validRepeats; } edescr->offset += sz_of_len; } ctx->repeats = edescr->validRepeats; if (edescr->bitstring) { ctx->repeats = (ctx->repeats+7)/8; } edescr->bytelen = edescr->bytelen * ctx->repeats; } if (edescr->ptrtype != noptr) { char* pointer = value; vb = (char*) &pointer; len = sizeof (char*); } else { vb = (char*) value; len = edescr->bytelen; if ((edescr->btype == T_issdu) || (edescr->btype == T_buffer)) { USHORT l_buf, o_buf; /* * For the structure SDU perform a special handling. * The SDU contains l_buf and o_buf and the element * buf. This element is only defined as buf[1] because * the real length results of the encoded message and * must be calculated form l_buf and o_buf */ /* * read l_buf and o_buf (length and offset) out of the value */ memcpy ((UBYTE *)&l_buf, vb, sizeof (USHORT)); memcpy ((UBYTE *)&o_buf, vb+sizeof (USHORT), sizeof (USHORT)); len = (2 * sizeof (USHORT)) + ((l_buf+o_buf+7)/8); if (handle) { if (edescr->ptrtype == noptr) handle->lenVarPart += (USHORT) len; else handle->lenVarPart += sizeof (void*); } edescr->bytelen = len; } } /* * write the value into the C-structure */ memcpy (cs+edescr->offset, vb, len); return CCDEDIT_OK; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_get_type | +--------------------------------------------------------------------+ PURPOSE : Requests the type (primitive or message) for a given name. The type is stored in the return parameter type. */ USHORT CCDDATA_PREF(cde_get_type) (char *name, T_ELM_SRC *type) { #ifdef CCD_SYMBOLS USHORT SAP, Opcode, Direction, Entity; /* * check the primitive table first. Look in all SAPs ands for * all direction alls opcodes to find the name as a primitve * name. */ for (SAP = 0; SAP <= ccddata_max_sap_num; SAP++) for (Direction = 0; Direction <= 1; Direction++) for (Opcode = 0; Opcode <= ccddata_max_primitive_id; Opcode++) if (ccddata_get_pmtx(SAP, Opcode, Direction) NEQ NO_REF) { if (!strcmp (name, pcomp[ccddata_get_pmtx(SAP, Opcode, Direction)].name)) { *type = FromPrim; return CCDEDIT_OK; } } /* * check the message table second. Look in all entities ands for * all direction alls opcodes to find the name as a message * name. */ for (Entity = 0; Entity < ccddata_num_of_entities; Entity++) for (Direction = 0; Direction <= 1; Direction++) for (Opcode = 0; Opcode <= ccddata_max_message_id; Opcode++) if (ccddata_get_mmtx(Entity, Opcode, Direction) NEQ NO_REF) { if (!strcmp (name, mcomp[ccddata_get_mmtx(Entity, Opcode, Direction)].name)) { *type = FromPrim; return CCDEDIT_OK; } } #endif return CCDEDIT_PRIM_NOT_FOUND; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_get_primcode | +--------------------------------------------------------------------+ PURPOSE : Requests the opcode of the primitive for a given name. The opcode is stored in the return parameter primcode. */ USHORT CCDDATA_PREF(cde_get_primcode) (char *name, ULONG *primcode) { #ifdef CCD_SYMBOLS USHORT SAP, Opcode, Direction; /* * check the primitive table. Look in all SAPs ands for * all direction alls opcodes to find the name as a primitve * name. */ for (SAP = 0; SAP <= ccddata_max_sap_num; SAP++) for (Direction = 0; Direction <= 1; Direction++) for (Opcode = 0; Opcode <= ccddata_max_primitive_id; Opcode++) if (ccddata_get_pmtx(SAP, Opcode, Direction) NEQ NO_REF) { if (!strcmp (name, pcomp[ccddata_get_pmtx(SAP, Opcode, Direction)].name)) { *primcode = ((Direction & 0x01) << 14); *primcode |= (SAP & 0x3fff); *primcode |= ((Opcode & 0xff) << 16); *primcode |= 0x80000000; return CCDEDIT_OK; } } #endif return CCDEDIT_PRIM_NOT_FOUND; } /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CCDEDIT | | STATE : code ROUTINE : cde_get_msgcode | +--------------------------------------------------------------------+ PURPOSE : Requests the opcode, the direction and the entity-number of the message for a given name. The opcode is stored in the return parameters . */ USHORT CCDDATA_PREF(cde_get_msgcode) (char *name, UBYTE *type, UBYTE *direction, UBYTE *entity) { #ifdef CCD_SYMBOLS USHORT Opcode, Direction, Entity; /* * check the message table. Look in all entities ands for * all direction alls opcodes to find the name as a message * name. */ for (Entity = 0; Entity < ccddata_num_of_entities; Entity++) for (Direction = 0; Direction <= 1; Direction++) for (Opcode = 0; Opcode <= ccddata_max_message_id; Opcode++) if (ccddata_get_mmtx(Entity, Opcode, Direction) NEQ NO_REF) { if (!strcmp (name, mcomp[ccddata_get_mmtx(Entity, Opcode, Direction)].name)) { *type = (UBYTE) Opcode; *direction = (UBYTE) Direction; *entity = (UBYTE) Entity; return CCDEDIT_OK; } } #endif return CCDEDIT_MESSAGE_NOT_FOUND; } /* +------------------------------------------------------------------------------ | Function : cde_get_is_downlink +------------------------------------------------------------------------------ | Description : This function finds out if an AIM is a downlink or uplink. | | Parameters : comp_index. | | Return : False if uplink otherwise true (downlink or both). +------------------------------------------------------------------------------ */ int CCDDATA_PREF(cde_get_is_downlink) (ULONG comp_index) { UBYTE ent; UBYTE msg_id; for(ent = 0; ent < ccddata_num_of_entities ; ent++) { for(msg_id = 0; msg_id <= ccddata_max_message_id ; msg_id++) { if(ccddata_get_mmtx (ent, msg_id, 1) == (USHORT)comp_index) return 1; } } return 0; } /* * The following functions are copied from ..\TAP\tdc_interface.c and * renamed to get the cde_ prefix instead of tdc_. * It should be checked if instead of these functions the usual approach * to ccdedit by the functions pairs cde_comp_first/cde_comp_next * (respectively their prim/msg pendants) can be used (maybe in combination * with cde_get_comp). If the check confirms to use the usual approach, * those 3 functions here should be deleted again */ /* +------------------------------------------------------------------------------ | Function : cde_get_comp_index +------------------------------------------------------------------------------ | Description : This function searches the comp index in either pcomp or mcomp | | Parameters : name and table type. | | Return : The table entry, if non found it returns 0xffffffff; +------------------------------------------------------------------------------ */ ULONG CCDDATA_PREF(cde_get_comp_index) (CHAR* comp_name, T_ELM_SRC table) { ULONG comp_index; BOOL found = FALSE; if (table == FromMsg) { /* * search the mcomp-table for the given name */ comp_index = 0; while (!found AND mcomp[comp_index].name NEQ NULL) { /* * composition name found */ if (strcmp (mcomp[comp_index].name, comp_name) EQ 0) found = TRUE; else comp_index++; } if(found) return comp_index; else return NO_ENTRY_FOUND; } else { /* * search the pcomp-table for the given name */ comp_index = 0; while (!found AND pcomp[comp_index].name NEQ NULL) { /* * composition name found */ if (strcmp (pcomp[comp_index].name, comp_name) EQ 0) found = TRUE; else comp_index++; } if(found) return comp_index; else return NO_ENTRY_FOUND; } } /* +------------------------------------------------------------------------------ | Function : cde_get_element_name +------------------------------------------------------------------------------ | Description : This function gets the element name for a given index + offset. | | Parameters : comp_index, offset and table type. | | Return : The element name. +------------------------------------------------------------------------------ */ CHAR* CCDDATA_PREF(cde_get_element_name) (ULONG comp_index, USHORT elem_off , T_ELM_SRC table) { if (table == FromMsg) { if (mcomp[comp_index].componentRef == -1 || elem_off >= mcomp[comp_index].numOfComponents) return NULL; return ccddata_get_alias ((USHORT) (mcomp[comp_index].componentRef + elem_off), table == FromMsg); } else if (pcomp[comp_index].componentRef == -1 || elem_off >= pcomp[comp_index].numOfComponents) return NULL; return ccddata_get_alias ((USHORT) (pcomp[comp_index].componentRef + elem_off), table == FromMsg); } /* +------------------------------------------------------------------------------ | Function : cde_get_array_kind +------------------------------------------------------------------------------ | Description : This function gets the array kind - e.g. the cSize of the | arrays (byte, short og long). | | Parameters : Name of the base type (var_name) and table type. | | Return : The cSize of the var_name. If not found it returns 0xffffffff +------------------------------------------------------------------------------ */ ULONG CCDDATA_PREF(cde_get_array_kind) (CHAR* var_name, T_ELM_SRC table) { ULONG var_index; BOOL found = FALSE; if (table == FromMsg) { /* * search the mvar-table for the given name */ var_index = 0; while (!found AND mvar[var_index].name NEQ NULL) { /* * name found */ if (strcmp (mvar[var_index].name, var_name) EQ 0) found = TRUE; else var_index++; } if(found) return (ULONG) mvar[var_index].cSize; else return NO_ENTRY_FOUND; } else { /* * search the pvar-table for the given name */ var_index = 0; while (!found AND pvar[var_index].name NEQ NULL) { /* * name found */ if (strcmp (pvar[var_index].name, var_name) EQ 0) found = TRUE; else var_index++; } if(found) return (ULONG) pvar[var_index].cSize; else return NO_ENTRY_FOUND; } }