FreeCalypso > hg > freecalypso-sw
diff gsm-fw/ccd/pdi.c @ 648:970d6199f2c5
gsm-fw/ccd/*.[ch]: initial import from the LoCosto source
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Thu, 04 Sep 2014 05:48:57 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/ccd/pdi.c Thu Sep 04 05:48:57 2014 +0000 @@ -0,0 +1,541 @@ +/* ++----------------------------------------------------------------------------- +| Project : +| Modul : pdi.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 : ++----------------------------------------------------------------------------- +*/ + +#define PDI_C + +#include "typedefs.h" +#include "ccdapi.h" +#include "ccdtable.h" +#include "ccddata.h" +#include <malloc.h> +#include <memory.h> +#include <string.h> +#include "pdi.h" + +#define GET_PD(m) ((m)->buf[((m)->o_buf)>>3] & 0x0f) +#define GET_TI(m) ((m)->buf[((m)->o_buf)>>3] >> 4) + +/* Constants borrowed from grr.h */ +#define CTRL_BLK_NO_OPT 1 +#define CTRL_BLK_OPT 2 + +static T_PDI_DECODEINFO* g_DummyDecodeInfo = NULL; + +static T_PDI_DECODEINFO m_def_dinfo[]={ + /* type */ /* attrib */ /* prim */ /* entity */ /* mt */ /* pdi_prepare_ccdmsg */ /* primmbr */ + {PDI_DECODETYPE_L3PDU_N, "sdu", "PH_*", "", 0xff, NULL, NULL}, + {PDI_DECODETYPE_L3PDU_N, "sdu", "MPH_*", "", 0xff, NULL, NULL}, + {PDI_DECODETYPE_L3PDU_N, "sdu", "DL_*", "", 0xff, NULL, NULL}, + {PDI_DECODETYPE_L3PDU, "sdu", "XX_TAP*", "", 0xff, NULL, NULL}, + {PDI_DECODETYPE_NOPD, "sdu", "XX_*", "XX", 0xff, NULL, NULL}, + {PDI_DECODETYPE_L3PDU, "sdu", "*", "", 0xff, NULL, NULL} +}; +#define DEF_DINFO_COUNT (sizeof(m_def_dinfo) / sizeof(*m_def_dinfo)) + +static UBYTE pdi_readmtype (T_MSGBUF* msg, UBYTE len) +{ + UBYTE mt = msg->buf[msg->o_buf>>3] >> (8-len); + msg->l_buf -= len; + msg->o_buf += len; + return mt; +} + +#define PDI_MBUFLEN 1024 +static struct +{ + U16 l_buf; + U16 o_buf; + char buf[PDI_MBUFLEN]; +} pdi_msgbuf; + +static int pdi_rmac_hdr (T_PDI_CCDMSG* ccdmsg, char* evalue, int evlen) +{ + char* ptr_blk; + UBYTE payload, rrbp, sp; + evalue++; /* Assume it is an array and skip length delivered from ccdedit */ + memcpy (pdi_msgbuf.buf, evalue, evlen > PDI_MBUFLEN ? PDI_MBUFLEN : evlen); + ptr_blk = evalue; + pdi_msgbuf.l_buf = evlen * 8; + pdi_msgbuf.o_buf = 0; + ccdmsg->mbuf = (T_MSGBUF*) &pdi_msgbuf; + + /* the following is borrowed from grlc_gfff.c */ + payload = (ptr_blk[0] & 0xC0) >> 6; + rrbp = (ptr_blk[0] & 0x30) >> 4; + sp = (ptr_blk[0] & 0x08) >> 3; + + if (payload == CTRL_BLK_NO_OPT) + { + /* msg starts at byte #2 */ + pdi_msgbuf.l_buf -= 8; + pdi_msgbuf.o_buf += 8; + } + else if ((payload == CTRL_BLK_OPT) && + !(ptr_blk[1] & 0x01) && + !(ptr_blk[1] & 0x80) && + (ptr_blk[1] & 0x02)) + { + /* msg starts at byte #3 */ + pdi_msgbuf.l_buf -= 16; + pdi_msgbuf.o_buf += 16; + } + else if ((payload == CTRL_BLK_OPT) && + (ptr_blk[1] & 0x01) && + !(ptr_blk[1] & 0x80) && + (ptr_blk[1] & 0x02)) + { + /* msg starts at byte #4 */ + pdi_msgbuf.l_buf -= 24; + pdi_msgbuf.o_buf += 24; + } + else + { + return PDI_NONE; + } + return PDI_CCDMSG; +} + +T_PDI_CONTEXT* CCDDATA_PREF(pdi_createDefContext)() +{ + const T_PDI_DECODEINFO* dinfo; + int dinfo_count=ccddata_get_pdi_dinfo(&dinfo); + if (dinfo_count==0) + { + dinfo_count=DEF_DINFO_COUNT; + dinfo=m_def_dinfo; + } + return CCDDATA_PREF(pdi_createContext)(dinfo,dinfo_count); +} + + +T_PDI_CONTEXT* CCDDATA_PREF(pdi_createContext)(const T_PDI_DECODEINFO *dinfo, unsigned int dicount) +{ + int i; + USHORT sap, opc, dir, di; + USHORT pmtx; + T_PDI_DECODEINFO* decodeInfo[1024]; + int decodeInfoCount; + int len; + + T_PDI_CONTEXT *context; + + if (context = (T_PDI_CONTEXT*)malloc(sizeof(T_PDI_CONTEXT))) + { + // copy dinfo + if (!(context->dinfo = (T_PDI_DECODEINFO*)malloc(sizeof(T_PDI_DECODEINFO)*dicount))) + { + free(context); + return NULL; + } + memcpy(context->dinfo, dinfo, sizeof(T_PDI_DECODEINFO)*dicount); + + // PD -> CCDENT + memset(context->PdEntityTable, -1, sizeof(T_PDI_PdEntityTable)); + context->PdEntityTable[PD_XX] = ccddata_get_ccdent("XX"); + context->PdEntityTable[PD_CC] = ccddata_get_ccdent("CC"); + context->PdEntityTable[PD_MM] = ccddata_get_ccdent("MM"); + context->PdEntityTable[PD_RR] = ccddata_get_ccdent("RR"); + context->PdEntityTable[PD_GMM] = ccddata_get_ccdent("GMM"); + context->PdEntityTable[PD_SMS] = ccddata_get_ccdent("SMS"); + context->PdEntityTable[PD_SS] = ccddata_get_ccdent("SS"); + context->PdEntityTable[PD_SM] = ccddata_get_ccdent("SM"); + context->PdEntityTable[PD_TST] = ccddata_get_ccdent("TST"); + + /* initialize mi_length */ + context->mi_length = ccddata_get_mi_length (); + + // count pcomp + i = 0; + while (ccddata_get_pcomp((USHORT)i)->name != NULL) i++; + context->PrimDecodeInfo = (T_PDI_DECODEINFO***)malloc(i*sizeof(T_PDI_DECODEINFO**)); + memset(context->PrimDecodeInfo, 0, i*sizeof(int*)); + + // search all primitives + for (sap = 0; sap <= ccddata_get_max_sap_num(); sap++) + for (opc = 0; opc <= (USHORT)ccddata_get_max_primitive_id(); opc++) + for (dir = 0; dir <= 1; dir++) + if ((pmtx = ccddata_get_pmtx(sap, opc, dir)) != NO_REF) + { + const char* pname; + pname = ccddata_get_pcomp(pmtx)->name; + + decodeInfoCount = 0; + for (di = 0; di < dicount; di++) + { + int wildcard; + len = strlen(context->dinfo[di].prim); + if (context->dinfo[di].prim[len-1] == '*') + { + wildcard = 1; + len--; + } + else + { + wildcard = 0; + len = strlen(pname); + } + + if (wildcard) + { + if (!strncmp(context->dinfo[di].prim, pname, len)) + { + decodeInfo[decodeInfoCount] = &context->dinfo[di]; + decodeInfoCount++; + } + } + else + { + if (!strcmp(context->dinfo[di].prim, pname)) + { + decodeInfo[decodeInfoCount] = &context->dinfo[di]; + decodeInfoCount++; + } + } + } + + // store decodeInfo for this primitive + if (decodeInfoCount != 0) + { + decodeInfo[decodeInfoCount] = g_DummyDecodeInfo; + decodeInfoCount++; + context->PrimDecodeInfo[pmtx] = (T_PDI_DECODEINFO**) + malloc(decodeInfoCount*sizeof(T_PDI_DECODEINFO*)); + if (context->PrimDecodeInfo+pmtx) + { + memcpy(context->PrimDecodeInfo[pmtx], &decodeInfo, + decodeInfoCount*sizeof(T_PDI_DECODEINFO*)); + + } + else + context->PrimDecodeInfo[pmtx] = &g_DummyDecodeInfo; + } + else + context->PrimDecodeInfo[pmtx] = &g_DummyDecodeInfo; + + } // endif (pmtx != NO_REF) + } + + return context; +} + + + +void CCDDATA_PREF(pdi_destroyContext)(T_PDI_CONTEXT *context) +{ + int i = 0; + + if (context==NULL) return; + + while (ccddata_get_pcomp((USHORT)i)->name != NULL) + { + if ((context->PrimDecodeInfo[i] != NULL) && + (context->PrimDecodeInfo[i][0] != NULL)) + free(context->PrimDecodeInfo[i]); + i++; + } + if (context->PrimDecodeInfo != NULL) + free(context->PrimDecodeInfo); + + free(context->dinfo); + + free(context); +} + + + +void CCDDATA_PREF(pdi_startPrim)(T_PDI_CONTEXT *context, ULONG opc) +{ + context->sapi = 0; + + if (opc & 0x80000000) + { + context->sap = (USHORT) (opc & 0x3fff); + context->opc = (USHORT) ((opc >> 16) & 0xff); + } + else + { + context->sap = (USHORT) (((opc & 0x3f00)>>8) & 0xff); + context->opc = (USHORT) (opc & 0xff); + } + context->dir = (UBYTE) (((opc & 0x4000)>>14) & 0x01); + + context->pmtx = ccddata_get_pmtx(context->sap, context->opc, context->dir); + context->mtypenum = 0; +} + +void CCDDATA_PREF(pdi_getDecodeInfo)(T_PDI_CONTEXT *context, const char *ename, + char *evalue, int evlen, T_PDI *decinfo) +{ + int i=0; + T_PDI_DECODEINFO* di; + + decinfo->decodetype = PDI_NONE; + + while (di = context->PrimDecodeInfo[context->pmtx][i++]) + { + if ((di->type == PDI_DECODETYPE_SAPI) && (strcmp(ename, "sapi") == 0)) + { + context->sapi = evalue[0]; + } + + if (!strcmp(ename, di->attrib)) + { + decinfo->pdi.ccdmsg.msg_type = 0xff; + + if (di->pdi_prepare_ccdmsg) + { + decinfo->decodetype = (*di->pdi_prepare_ccdmsg) + (&decinfo->pdi.ccdmsg, context->mtypeval, + context->mtypenum); + if (decinfo->decodetype == PDI_NONE) + { + continue; + } + } + + switch (di->type) + { + case PDI_DECODETYPE_AIM: + case PDI_DECODETYPE_AIM_N: + case PDI_DECODETYPE_AIM_CHECK: + case PDI_DECODETYPE_AIM_N_CHECK: + decinfo->decodetype = PDI_CCDMSG; + memcpy (pdi_msgbuf.buf, evalue, + evlen > PDI_MBUFLEN ? PDI_MBUFLEN : evlen); + pdi_msgbuf.l_buf = evlen * 8; + pdi_msgbuf.o_buf = 0; + + /* first byte: don't care */ + pdi_msgbuf.l_buf -= 8; + pdi_msgbuf.o_buf += 8; + decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*) &pdi_msgbuf; + decinfo->pdi.ccdmsg.pd = GET_PD (decinfo->pdi.ccdmsg.mbuf); + if (strcmp (di->entity, + CCDDATA_PREF(pdi_pd2name)(decinfo->pdi.ccdmsg.pd))) + { + /* pd does not match the configured entity */ + decinfo->decodetype = PDI_CCDMSG; + continue; + } + else + { + pdi_msgbuf.l_buf -= 8; + pdi_msgbuf.o_buf += 8; + } + //decinfo->pdi.ccdmsg.ti = GET_TI (decinfo->pdi.ccdmsg.mbuf); + decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_AIM) || + (di->type == PDI_DECODETYPE_AIM_CHECK) ? + context->dir : (~context->dir)&1; + decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity); + decinfo->pdi.ccdmsg.msg_type = pdi_readmtype ( + decinfo->pdi.ccdmsg.mbuf, + context->mi_length[decinfo->pdi.ccdmsg.entity]); + break; + case PDI_DECODETYPE_L3PDU_N: + case PDI_DECODETYPE_L3PDU: + decinfo->decodetype = PDI_CCDMSG; + + decinfo->pdi.ccdmsg.pd = GET_PD ((T_MSGBUF*) evalue); + decinfo->pdi.ccdmsg.ti = GET_TI ((T_MSGBUF*) evalue); + decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_L3PDU) ? + context->dir : (~context->dir)&1; + + decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue; + + if (CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd)==-1) + { + decinfo->decodetype = PDI_NONE; + } + else + { + decinfo->pdi.ccdmsg.entity = (UBYTE)CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd); + + ((T_MSGBUF*)evalue)->o_buf += 8; + ((T_MSGBUF*)evalue)->l_buf -= 8; + + decinfo->pdi.ccdmsg.msg_type = pdi_readmtype ((T_MSGBUF*)evalue, + context->mi_length[decinfo->pdi.ccdmsg.entity]); + } + + /* remove SSN bit */ + if (!strcmp ("DL_DATA_REQ", ccddata_get_pcomp (context->pmtx)->name)) + { + if (decinfo->pdi.ccdmsg.pd == PD_CC || + decinfo->pdi.ccdmsg.pd == PD_MM || + decinfo->pdi.ccdmsg.pd == PD_SS) + { + decinfo->pdi.ccdmsg.msg_type &= ~0x40; + } + } + break; + + case PDI_DECODETYPE_NOPD: + case PDI_DECODETYPE_NOPD_N: + case PDI_DECODETYPE_RR_SHORT: + decinfo->decodetype = PDI_CCDMSG; + + decinfo->pdi.ccdmsg.pd = 0; + decinfo->pdi.ccdmsg.ti = 0; + decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_NOPD) ? + context->dir : (~context->dir)&1; + + decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue; + decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity); + decinfo->pdi.ccdmsg.msg_type = pdi_readmtype ((T_MSGBUF*)evalue, + context->mi_length[decinfo->pdi.ccdmsg.entity]); + break; + + case PDI_DECODETYPE_NOPD_NOTYPE: + case PDI_DECODETYPE_NOPD_NOTYPE_N: + decinfo->decodetype = PDI_CCDMSG; + + decinfo->pdi.ccdmsg.pd = 0; + decinfo->pdi.ccdmsg.ti = 0; + decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_NOPD_NOTYPE) ? + context->dir : (~context->dir)&1; + + decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue; + + if (decinfo->pdi.ccdmsg.msg_type == 0xff) + { + decinfo->pdi.ccdmsg.msg_type = di->msg_type; + } + + decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity); + break; + + case PDI_DECODETYPE_MAC_H: + case PDI_DECODETYPE_MAC_H_N: + case PDI_DECODETYPE_MAC_H_CHECK: + case PDI_DECODETYPE_MAC_H_N_CHECK: + if ((decinfo->decodetype = pdi_rmac_hdr (&decinfo->pdi.ccdmsg, + evalue, evlen)) == PDI_CCDMSG) + { + decinfo->pdi.ccdmsg.pd = 0; + decinfo->pdi.ccdmsg.ti = 0; + decinfo->pdi.ccdmsg.dir = ((di->type == PDI_DECODETYPE_MAC_H) || + (di->type == PDI_DECODETYPE_MAC_H_CHECK)) + ? context->dir : (~context->dir)&1; + decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity); + decinfo->pdi.ccdmsg.msg_type = + pdi_readmtype (decinfo->pdi.ccdmsg.mbuf, + context->mi_length[decinfo->pdi.ccdmsg.entity]); + } + break; + + case PDI_DECODETYPE_SAPI: + decinfo->decodetype = PDI_NONE; + if (context->sapi == 1) // only sapi1 (GMM) has data for ccd + { + decinfo->decodetype = PDI_CCDMSG; + + decinfo->pdi.ccdmsg.pd = GET_PD ((T_MSGBUF*) evalue); + decinfo->pdi.ccdmsg.ti = GET_TI ((T_MSGBUF*) evalue); + decinfo->pdi.ccdmsg.dir = context->dir; + +/* !!! TBD !!! */ + /* find msg_type*/ +/* !!! TBD !!! */ + + decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue; + + ((T_MSGBUF*)evalue)->o_buf += 8; + ((T_MSGBUF*)evalue)->l_buf -= 8; + + if (CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd)==-1) + { + decinfo->decodetype = PDI_NONE; + } + else + { + decinfo->pdi.ccdmsg.entity = (UBYTE)CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd); + } + } + break; + + default: + decinfo->decodetype = PDI_NONE; + } + + break; + } /* endif (strcmp) */ + else + { + if (evlen > 4 || evlen < 0 || evlen == 3) + { + /* don't check prim members for non base types */ + continue; + } + /* check for prim members later needed for finding out msg type */ + if (di->primmbr) + { + int i; + for (i=0; di->primmbr[i] && context->mtypenum<PDI_MAXPMEMFORMTYPE; i++) + { + if (!strcmp(ename, di->primmbr[i])) + { + switch (evlen) + { + case 1: + context->mtypeval[context->mtypenum++] = + (ULONG) * (UBYTE*) evalue; + break; + case 2: + context->mtypeval[context->mtypenum++] = + (ULONG) * (USHORT*) evalue; + break; + case 4: + default: + context->mtypeval[context->mtypenum++] = * (ULONG*) evalue; + break; + } + } + } + } + } + } /* endwhile */ + +} + +short CCDDATA_PREF(pdi_getEntityByPD)(const T_PDI_CONTEXT *context, unsigned char pd) +{ + if ((pd > 16) || (context->PdEntityTable == NULL)) + return -1; + else + return context->PdEntityTable[pd]; +} + + +const char* CCDDATA_PREF(pdi_pd2name)(unsigned char pd) +{ + switch (pd) { + case PD_XX: return "XX"; + case PD_CC: return "CC"; + case PD_MM: return "MM"; + case PD_RR: return "RR"; + case PD_GMM: return "GMM"; + case PD_SMS: return "SMS"; + case PD_SS: return "SS"; + case PD_SM: return "SM"; + case PD_TST: return "TST"; + + default: return "??"; + } +}