diff src/aci2/aci/psa_ssf.c @ 3:93999a60b835

src/aci2, src/condat2: import of g23m/condat source pieces from TCS211
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 26 Sep 2016 00:29:36 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/aci2/aci/psa_ssf.c	Mon Sep 26 00:29:36 2016 +0000
@@ -0,0 +1,1608 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  GSM-PS (6147)
+|  Modul   :  PSA_SSF
++----------------------------------------------------------------------------- 
+|  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 :  This module defines the functions for the protocol
+|             stack adapter for supplementary services.
++----------------------------------------------------------------------------- 
+*/ 
+
+#ifndef PSA_SSF_C
+#define PSA_SSF_C
+#endif
+
+#include "aci_all.h"
+
+#undef TRACING
+
+/*==== INCLUDES ===================================================*/
+#include "aci_cmh.h"
+#include "ati_cmd.h"
+#include "aci_cmd.h"
+
+#include "ksd.h"
+#include "aci.h"
+#include "psa.h"
+#include "psa_ss.h"
+#include "psa_util.h"
+#include "cmh_ss.h"
+
+/*==== CONSTANTS ==================================================*/
+#define MAX_MOSTI_NR    (7)     /* max number of ti's for MOS */
+
+#define MAX_ITM         (5)     /* max number of items per line */
+#define ITM_WDT         (14)    /* item width in chars */
+#define HDR_WDT         (10)    /* header width in chars */
+
+/*==== TYPES ======================================================*/
+
+
+/*==== EXPORT =====================================================*/
+
+/*==== VARIABLES ==================================================*/
+LOCAL UBYTE tiPool = 0xFF; /* holds pool of transaction identifiers */
+
+/*==== FUNCTIONS ==================================================*/
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmEmptyRslt      |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble an empty return result facility information
+            element.
+
+*/
+
+GLOBAL void psaSS_asmEmptyRslt ( void )
+{
+  TRACE_FUNCTION("psaSS_asmEmptyRslt");
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+
+  ssFIECodeBuf.l_buf = 8;
+
+  ssShrdPrm.cmpType = CT_RET_RSLT;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmErrorRslt      |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble an return error facility information
+            element.
+
+*/
+
+GLOBAL void psaSS_asmErrorRslt ( SHORT sId, UBYTE err )
+{
+  TRACE_FUNCTION("psaSS_asmErrorRslt");
+
+  ssShrdPrm.stb[sId].failType = SSF_SS_ERR;
+  ssShrdPrm.stb[sId].errCd    = err;
+  ssShrdPrm.cmpType = CT_RET_ERR;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmInterrogateSS  |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the interrogate SS facility information element.
+
+*/
+
+GLOBAL void psaSS_asmInterrogateSS ( UBYTE ssCode,
+                                     UBYTE bscSrvType,
+                                     UBYTE bscSrv  )
+{
+  MCAST( irgtSS, INTERROGATE_SS_INV );
+
+  TRACE_FUNCTION("psaSS_asmInterrogateSS");
+
+  memset( irgtSS, 0, sizeof( T_INTERROGATE_SS_INV ));
+
+  /* set basic settings */
+  irgtSS->msg_type  = INTERROGATE_SS_INV;
+  irgtSS->v_ssForBS = TRUE;
+
+  /* set service code */
+  irgtSS->ssForBS.v_ssCode = TRUE;
+  irgtSS->ssForBS.ssCode   = ssCode;
+
+  /* set basic service type */
+  switch( bscSrvType )
+  {
+    case( BS_BEAR_SRV ):
+
+      irgtSS->ssForBS.basicService.v_bearerService = TRUE;
+      irgtSS->ssForBS.basicService.bearerService   = bscSrv;
+      break;
+
+    case( BS_TELE_SRV ):
+
+      irgtSS->ssForBS.basicService.v_teleservice = TRUE;
+      irgtSS->ssForBS.basicService.teleservice   = bscSrv;
+      break;
+
+    default:
+      irgtSS->ssForBS.basicService.v_bearerService = FALSE;
+      irgtSS->ssForBS.basicService.v_teleservice = FALSE;
+  }
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmRegisterSS     |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the register SS facility information element.
+
+*/
+
+GLOBAL void  psaSS_asmRegisterSS    ( UBYTE ssCode, UBYTE bscSrvType,
+                                      UBYTE bscSrv, UBYTE ton, UBYTE npi,
+                                      UBYTE *num, UBYTE tos, UBYTE oe,
+                                      UBYTE *sub, UBYTE time )
+{
+  MCAST( regSS, REGISTER_SS_INV );
+
+  TRACE_FUNCTION("psaSS_asmRegisterSS");
+
+  memset( regSS, 0, sizeof( T_REGISTER_SS_INV ));
+
+  /* set basic settings */
+  regSS->msg_type        = REGISTER_SS_INV;
+  regSS->v_registerSSArg = TRUE;
+
+  /* set service code */
+  regSS->registerSSArg.v_ssCode = TRUE;
+  regSS->registerSSArg.ssCode   = ssCode;
+
+  /* set basic service type */
+  switch( bscSrvType )
+  {
+    case( BS_BEAR_SRV ):
+
+      regSS->registerSSArg.basicService.v_bearerService = TRUE;
+      regSS->registerSSArg.basicService.bearerService   = bscSrv;
+      break;
+
+    case( BS_TELE_SRV ):
+
+      regSS->registerSSArg.basicService.v_teleservice = TRUE;
+      regSS->registerSSArg.basicService.teleservice   = bscSrv;
+      break;
+  }
+
+  /* set forwarded to number */
+  if( num NEQ NULL )
+  {
+    regSS->registerSSArg.v_forwardedToNumber = TRUE;
+    regSS->registerSSArg.forwardedToNumber.c_bcdDigit
+        = (UBYTE)utl_dialStr2BCD((char *) num,
+                                 regSS->registerSSArg.forwardedToNumber.bcdDigit,
+                                 MAX_PARTY_NUM);
+
+    if(ton NEQ TON_NOT_PRES AND
+       npi NEQ NPI_NOT_PRES)
+    {
+      regSS->registerSSArg.forwardedToNumber.v_noa = TRUE;
+      regSS->registerSSArg.forwardedToNumber.noa   = ton;
+
+      regSS->registerSSArg.forwardedToNumber.v_npi = TRUE;
+      regSS->registerSSArg.forwardedToNumber.npi   = npi;
+    }
+  }
+
+  /* set forwarded to subaddress */
+  if( sub NEQ NULL )
+  {
+    regSS->registerSSArg.v_forwardedToSubaddress = TRUE;
+    regSS->registerSSArg.forwardedToSubaddress.c_bcdDigit
+        = (UBYTE)utl_dialStr2BCD((char *) sub,
+                                 regSS->registerSSArg.forwardedToSubaddress.bcdDigit,
+                                 MAX_SUBADDR_NUM);
+
+    regSS->registerSSArg.forwardedToSubaddress.v_tos = TRUE;
+    regSS->registerSSArg.forwardedToSubaddress.tos   = tos;
+
+    regSS->registerSSArg.forwardedToSubaddress.v_oei = TRUE;
+    regSS->registerSSArg.forwardedToSubaddress.oei   = oe;
+  }
+
+  /* set no reply timer */
+  if( ssCode EQ SS_CD_CFNRY AND time NEQ KSD_TIME_NONE )
+  {
+    regSS->registerSSArg.v_noReplyConditionTime = TRUE;
+    regSS->registerSSArg.noReplyConditionTime   = time;
+  }
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmEraseSS        |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the erase SS facility information element.
+
+*/
+
+GLOBAL void psaSS_asmEraseSS ( UBYTE ssCode, UBYTE bscSrvType,
+                               UBYTE bscSrv )
+{
+  MCAST( ersSS, ERASE_SS_INV );
+
+  TRACE_FUNCTION("psaSS_asmEraseSS");
+
+  memset( ersSS, 0, sizeof( T_ERASE_SS_INV ));
+
+  /* set basic settings */
+  ersSS->msg_type  = ERASE_SS_INV;
+  ersSS->v_ssForBS = TRUE;
+
+  /* set service code */
+  ersSS->ssForBS.v_ssCode = TRUE;
+  ersSS->ssForBS.ssCode   = ssCode;
+
+  /* set basic service type */
+  switch( bscSrvType )
+  {
+    case( BS_BEAR_SRV ):
+
+      ersSS->ssForBS.basicService.v_bearerService = TRUE;
+      ersSS->ssForBS.basicService.bearerService   = bscSrv;
+      break;
+
+    case( BS_TELE_SRV ):
+
+      ersSS->ssForBS.basicService.v_teleservice = TRUE;
+      ersSS->ssForBS.basicService.teleservice   = bscSrv;
+      break;
+  }
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmActivateSS     |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the interrogate SS facility information element.
+
+*/
+
+GLOBAL void psaSS_asmActivateSS ( UBYTE ssCode, UBYTE bscSrvType,
+                                   UBYTE bscSrv )
+{
+  MCAST( actSS, ACTIVATE_SS_INV );
+
+  TRACE_FUNCTION("psaSS_asmActivateSS");
+
+  memset( actSS, 0, sizeof( T_ACTIVATE_SS_INV ));
+
+  /* set basic settings */
+  actSS->msg_type  = ACTIVATE_SS_INV;
+  actSS->v_ssForBS = TRUE;
+
+  /* set service code */
+  actSS->ssForBS.v_ssCode = TRUE;
+  actSS->ssForBS.ssCode   = ssCode;
+
+  /* set basic service type */
+  switch( bscSrvType )
+  {
+    case( BS_BEAR_SRV ):
+
+      actSS->ssForBS.basicService.v_bearerService = TRUE;
+      actSS->ssForBS.basicService.bearerService   = bscSrv;
+      break;
+
+    case( BS_TELE_SRV ):
+
+      actSS->ssForBS.basicService.v_teleservice = TRUE;
+      actSS->ssForBS.basicService.teleservice   = bscSrv;
+      break;
+  }
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmDeactivateSS   |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the deactivate SS facility information element.
+
+*/
+
+GLOBAL void psaSS_asmDeactivateSS ( UBYTE ssCode, UBYTE bscSrvType,
+                                     UBYTE bscSrv )
+{
+  MCAST( deactSS, DEACTIVATE_SS_INV );
+
+  TRACE_FUNCTION("psaSS_asmDeactivateSS");
+
+  memset( deactSS, 0, sizeof( T_DEACTIVATE_SS_INV ));
+
+  /* set basic settings */
+  deactSS->msg_type  = DEACTIVATE_SS_INV;
+  deactSS->v_ssForBS = TRUE;
+
+  /* set service code */
+  deactSS->ssForBS.v_ssCode = TRUE;
+  deactSS->ssForBS.ssCode   = ssCode;
+
+  /* set basic service type */
+  switch( bscSrvType )
+  {
+    case( BS_BEAR_SRV ):
+
+      deactSS->ssForBS.basicService.v_bearerService = TRUE;
+      deactSS->ssForBS.basicService.bearerService   = bscSrv;
+      break;
+
+    case( BS_TELE_SRV ):
+
+      deactSS->ssForBS.basicService.v_teleservice = TRUE;
+      deactSS->ssForBS.basicService.teleservice   = bscSrv;
+      break;
+  }
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmRegisterPWD    |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the register password facility information
+            element.
+
+*/
+
+GLOBAL void psaSS_asmRegisterPWD ( UBYTE ssCode )
+{
+  MCAST( regPWD, REGISTER_PWD_INV );
+
+  TRACE_FUNCTION("psaSS_asmRegisterPWD");
+
+  memset( regPWD, 0, sizeof( T_REGISTER_PWD_INV ));
+
+  /* set service code */
+  regPWD->v_ssCode = TRUE;
+  regPWD->ssCode   = ssCode;
+  regPWD->msg_type = REGISTER_PWD_INV;
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmVerifyPWD      |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the verify password facility information
+            element.
+
+*/
+
+GLOBAL void psaSS_asmVerifyPWD ( UBYTE *pwd )
+{
+  MCAST( vrfPWD, GET_PWD_RES );
+
+  TRACE_FUNCTION("psaSS_asmVerifyPWD");
+
+  memset( vrfPWD, 0, sizeof( T_GET_PWD_RES ));
+
+  /* set service code */
+  vrfPWD->v_currPassword = TRUE;
+  vrfPWD->msg_type = GET_PWD_RES;
+
+  strncpy( (char *) vrfPWD->currPassword.digit, (char *) pwd, MAX_PWD_NUM );
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_RET_RSLT;
+
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmProcUSSDReq    |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the process USSD request facility information
+            element.
+
+*/
+
+GLOBAL void psaSS_asmProcUSSDReq ( UBYTE dcs, UBYTE *ussd, UBYTE len )
+{
+/*  UBYTE cmpLen;*/
+
+  MCAST( ussdReq, PROCESS_USSD_REQ_INV );
+
+  TRACE_FUNCTION("psaSS_asmProcUSSDReq");
+
+  memset( ussdReq, 0, sizeof( T_PROCESS_USSD_REQ_INV ));
+
+  /* set service code */
+  ussdReq->v_ussdArg = TRUE;
+  ussdReq->msg_type = PROCESS_USSD_REQ_INV;
+
+  /* set data coding scheme */
+  ussdReq->ussdArg.v_ussdDataCodingScheme = TRUE;
+  ussdReq->ussdArg.ussdDataCodingScheme   = dcs;
+
+  /* set ussd response string */
+/*  if( utl_getAlphabetCb( dcs ) EQ 0 ) *//* 7bit alphabet */
+/*    cmpLen = utl_cvt8To7( ussd, (UBYTE)MINIMUM( MAX_USSD_STRING, len),
+                          ussdReq->ussdArg.ussdString.b_ussdString, 0 );
+    else*/
+  {
+/*    cmpLen = len;*/
+    memcpy( ussdReq->ussdArg.ussdString.b_ussdString, ussd,
+            MINIMUM( MAX_USSD_STRING, len));
+  }
+
+  ussdReq->ussdArg.v_ussdString = TRUE;
+  ussdReq->ussdArg.ussdString.o_ussdString = 0;
+  ussdReq->ussdArg.ussdString.l_ussdString = len<<3; /*cmpLen<<3;*/
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmCnfUSSDReq     |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the confirm USSD request facility information
+            element.
+*/
+
+GLOBAL void psaSS_asmCnfUSSDReq ( UBYTE dcs, UBYTE *ussd, UBYTE len )
+{
+  UBYTE cmpLen;
+  UBYTE src_len;
+
+  MCAST( ussdReq, USSD_REQ_RES );
+
+  TRACE_FUNCTION("psaSS_asmCnfUSSDReq");
+
+  memset( ussdReq, 0, sizeof( T_USSD_REQ_RES ));
+
+  /* set service code */
+  ussdReq->v_ussdRes = TRUE;
+  ussdReq->msg_type = USSD_REQ_RES;
+
+  /* set data coding scheme */
+  ussdReq->ussdRes.v_ussdDataCodingScheme = TRUE;
+  ussdReq->ussdRes.ussdDataCodingScheme   = dcs;
+
+  /* set ussd response string */
+  if( utl_getAlphabetCb( dcs ) EQ 0 ) /* 7bit alphabet */
+  {
+    src_len = (UBYTE)MINIMUM( MAX_USSD_STRING, len);
+    cmpLen = utl_cvt8To7( ussd, src_len,
+                          ussdReq->ussdRes.ussdString.b_ussdString, 0 );
+    /* According to spec 23.038 section 6.1.2.3 for USSD packing, for bytes end with
+     * (8*n)-1 i.e where n is 1,2,3....i.e byte 7, 15, 23 ... to be padded 
+     * with carriage return <CR>(0xD) 
+     */
+    if ((src_len+1)%8 EQ 0)
+    {
+      ussdReq->ussdRes.ussdString.b_ussdString[cmpLen-1] |= (0xD << 1);
+    }
+  }
+  else
+  {
+    cmpLen = len;
+    memcpy( ussdReq->ussdRes.ussdString.b_ussdString, ussd,
+            MINIMUM( MAX_USSD_STRING, len));
+  }
+
+  ussdReq->ussdRes.v_ussdString = TRUE;
+  ussdReq->ussdRes.ussdString.o_ussdString = 0;
+  ussdReq->ussdRes.ussdString.l_ussdString = cmpLen<<3;
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_RET_RSLT;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_USSDProt1         |
++-------------------------------------------------------------------+
+
+  PURPOSE : send USSD according to protocol version 1.
+*/
+
+GLOBAL BOOL psaSS_asmUSSDProt1 ( SHORT sId )
+{
+  UBYTE  ussdBuf8Bit[MAX_USSD_STRING];   /* buffers 8 bit ussd string */
+  USHORT ussdLen8Bit;
+
+  TRACE_FUNCTION("psaSS_asmUSSDProt1");
+
+  if( ssShrdPrm.ussdLen AND
+      ssShrdPrm.stb[sId].SSver NEQ NOT_PRESENT_8BIT )
+  {
+    MCAST( ussdData, PROCESS_USSD_INV );
+
+    memset( ussdData, 0, sizeof( T_PROCESS_USSD_INV ));
+
+    /* set service code */
+    ussdData->v_ssUserData = TRUE;
+    ussdData->msg_type = PROCESS_USSD_INV;
+
+    /* GSM data must be 8-bit coded */
+    if (ssShrdPrm.ussdDcs EQ 0x0F)
+    {
+      ussdLen8Bit = utl_cvt7To8 (ssShrdPrm.ussdBuf, ssShrdPrm.ussdLen, ussdBuf8Bit, 0);
+    }
+    else
+    {
+      memcpy ( ussdBuf8Bit, ssShrdPrm.ussdBuf, ssShrdPrm.ussdLen);
+               ussdLen8Bit = ssShrdPrm.ussdLen;
+    }
+
+    /* set ussd data string, if convertible */
+    if( !utl_cvtGsmIra ( ussdBuf8Bit,
+                         ussdLen8Bit,
+                         ussdData->ssUserData.b_ssUserData,
+                         MAX_USSD_DATA,
+                         CSCS_DIR_GsmToIra ) )
+    {
+      return( FALSE );
+    }
+
+    ussdData->ssUserData.o_ssUserData = 0;
+    ussdData->ssUserData.l_ssUserData = ssShrdPrm.ussdLen<<3;
+
+    memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+    ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+    ccd_codeMsg (CCDENT_FAC, UPLINK,
+                 (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+                 NOT_PRESENT_8BIT);
+
+    ssShrdPrm.cmpType = CT_INV;
+
+    /* skip SS version indicator */
+    ssShrdPrm.stb[sId].SSver = NOT_PRESENT_8BIT;
+
+    /* repeat USSD string */
+    psaSS_NewTrns(sId);
+
+    return( TRUE );
+  }
+
+  return( FALSE );
+}
+
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_asmDeactivateCCBS |
++-------------------------------------------------------------------+
+
+  PURPOSE : assemble the deactivate CCBS facility information
+            element.
+
+*/
+
+GLOBAL void psaSS_asmDeactivateCCBS ( UBYTE idx )
+{
+  MCAST( ersCCBS, ERASE_CC_ENTRY_INV );
+
+  TRACE_FUNCTION("psaSS_asmDeactivateCCBS");
+
+  memset( ersCCBS, 0, sizeof( T_ERASE_CC_ENTRY_INV ));
+
+  /* set service code */
+  ersCCBS->v_eraseCCEntryArg = TRUE;
+  ersCCBS->msg_type = ERASE_CC_ENTRY_INV;
+
+  ersCCBS->eraseCCEntryArg.v_ssCode = TRUE;
+  ersCCBS->eraseCCEntryArg.ssCode   = SS_CD_CCBS;
+
+  if( idx NEQ KSD_IDX_NONE )
+  {
+    ersCCBS->eraseCCEntryArg.v_ccbsIndex = TRUE;
+    ersCCBS->eraseCCEntryArg.ccbsIndex   = idx;
+  }
+
+  memset( &ssFIECodeBuf, 0, sizeof( ssFIECodeBuf ));
+  ssFIECodeBuf.l_buf = MAX_FIE_CODE_BUF_LEN<<3;
+  ccd_codeMsg (CCDENT_FAC, UPLINK,
+               (T_MSGBUF *)&ssFIECodeBuf, _decodedMsg,
+               NOT_PRESENT_8BIT);
+
+  ssShrdPrm.cmpType = CT_INV;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_dasmInvokeCmp     |
++-------------------------------------------------------------------+
+
+  PURPOSE : disassemble the result component.
+*/
+
+GLOBAL void psaSS_dasmInvokeCmp ( SHORT sId, T_inv_comp *invCmp )
+{
+  USHORT ivId;                /* holds invoke Id */
+  UBYTE  opCode;              /* holds operation code */
+
+  TRACE_FUNCTION("psaSS_dasmInvokeCmp");
+
+  if( invCmp -> v_inv_id )
+    ivId = invCmp -> inv_id;
+  else
+    ivId = NOT_PRESENT_16BIT;
+
+  if( invCmp -> v_op_code )
+    opCode = invCmp -> op_code;
+  else
+    opCode = NOT_PRESENT_8BIT;
+
+  /* store op code and invoke id for result */
+  ssShrdPrm.stb[sId].iId = (UBYTE)ivId;
+  ssShrdPrm.stb[sId].opCode = opCode;
+
+  if( invCmp -> params.l_params )
+  {
+    UBYTE ccdRet;
+
+    memcpy( ssFIEDecodeBuf, &invCmp -> params, FACILITY_LEN );
+
+    ccdRet = ccd_decodeMsg (CCDENT_FAC,
+                            DOWNLINK,
+                            (T_MSGBUF *) ssFIEDecodeBuf,
+                            (UBYTE    *) _decodedMsg,
+                            opCode);
+
+    if( ccdRet NEQ ccdOK )
+    {
+      TRACE_EVENT_P1("CCD Decoding Error: %d",ccdRet );
+      ssShrdPrm.stb[sId].failType = SSF_CCD_DEC;
+      cmhSS_TransFail(sId);
+    }
+  }
+  else
+    memset( ssFIEDecodeBuf, 0, FACILITY_LEN );  /* put all valid flags to FALSE */
+
+  switch( opCode )
+  {
+    case( OPC_GET_PASSWORD ):
+      {
+        MCAST( getPWD, GET_PWD_INV );
+
+        cmhSS_getPassword( sId, getPWD );
+      }
+      break;
+
+    case( OPC_UNSTRUCT_SS_NOTIFY ):
+      {
+        MCAST( ussdNtfy, USSD_NOTIFY_INV );
+
+        cmhSS_USSDNotify( sId, ussdNtfy );
+      }
+      break;
+
+    case( OPC_UNSTRUCT_SS_REQ ):
+      {
+        MCAST( ussdReq, USSD_REQ_INV );
+
+        cmhSS_USSDRequest( sId, ussdReq );
+      }
+      break;
+
+    case( OPC_FWD_CHECK_SS_IND ):
+      {
+        cmhSS_FwdChckSS( sId );
+      }
+      break;
+  }
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_dasmResultCmp     |
++-------------------------------------------------------------------+
+
+  PURPOSE : disassemble the result component.
+*/
+
+GLOBAL void psaSS_dasmResultCmp ( SHORT sId, T_res_comp *resCmp )
+{
+  UBYTE  opCode;              /* holds operation code */
+
+  TRACE_FUNCTION("psaSS_dasmResultCmp");
+
+  /* get operation code of the result */
+  if( resCmp -> v_sequence         AND 
+      resCmp -> sequence.v_op_code )
+  {
+    opCode = resCmp -> sequence.op_code;
+  }
+  else
+    opCode = ssShrdPrm.stb[sId].opCode;
+
+  /* decode additional parameters of result */
+  if( resCmp -> v_sequence               AND 
+      resCmp -> sequence.params.l_params )
+  {
+    UBYTE ccdRet;
+
+    memcpy( ssFIEDecodeBuf, &resCmp -> sequence.params, FACILITY_LEN);
+
+    ccdRet = ccd_decodeMsg (CCDENT_FAC,
+                            DOWNLINK,
+                            (T_MSGBUF *) ssFIEDecodeBuf,
+                            (UBYTE    *) _decodedMsg,
+                            opCode);
+
+    if( ccdRet NEQ ccdOK )
+    {
+      CHAR buf[25];
+      sprintf( buf, "CCD Decoding Error: %d",ccdRet );
+      TRACE_EVENT( buf );
+      cmhSS_SSResultFailure( sId );
+      return;
+    }
+  }
+
+  /* determine to which operation the result belongs to */
+  switch( opCode )
+  {
+    case( OPC_REGISTER_SS ):
+      {
+        MCAST( regSS, REGISTER_SS_RES );
+
+        cmhSS_SSRegistrated( sId, regSS );
+      }
+      break;
+
+    case( OPC_ERASE_SS ):
+      {
+        MCAST( ersSS, ERASE_SS_RES );
+
+        cmhSS_SSErased( sId, ersSS );
+      }
+      break;
+
+    case( OPC_ACTIVATE_SS ):
+      {
+        MCAST( actSS, ACTIVATE_SS_RES );
+
+        if( !(resCmp -> v_sequence) OR !(resCmp -> sequence.params.l_params) )
+        {
+          memset(actSS, 0, sizeof(T_ACTIVATE_SS_RES));
+        }
+        cmhSS_SSActivated( sId, actSS );
+      }
+      break;
+
+    case( OPC_DEACTIVATE_SS ):
+      {
+        MCAST( deactSS, DEACTIVATE_SS_RES );
+
+        cmhSS_SSDeactivated( sId, deactSS );
+      }
+      break;
+
+    case( OPC_INTERROGATE_SS ):
+      {
+        MCAST( irgtSS, INTERROGATE_SS_RES );
+
+        cmhSS_SSInterrogated( sId, irgtSS );
+      }
+      break;
+
+    case( OPC_REGISTER_PASSWORD ):
+      {
+        MCAST( regPWD, REGISTER_PWD_RES );
+
+        cmhSS_SSPWDRegistrated( sId, regPWD );
+      }
+      break;
+
+    case( OPC_PROC_UNSTRUCT_SS_DATA ):
+      {
+        MCAST( prcUSSDDat, PROCESS_USSD_RES );
+
+        cmhSS_USSDDatProcessed( sId, prcUSSDDat );
+      }
+      break;
+
+    case( OPC_PROC_UNSTRUCT_SS_REQ ):
+      {
+        MCAST( prcUSSDReq, PROCESS_USSD_REQ_RES );
+
+        cmhSS_USSDReqProcessed( sId, prcUSSDReq );
+      }
+      break;
+
+    case( OPC_ERASE_CC_ENTRY ):
+      {
+        MCAST( ersCCNtry, ERASE_CC_ENTRY_RES );
+
+        cmhSS_CCNtryErased( sId, ersCCNtry );
+      }
+      break;
+  }
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_dasmErrorCmp      |
++-------------------------------------------------------------------+
+
+  PURPOSE : disassemble the error component.
+*/
+
+GLOBAL T_ACI_RETURN psaSS_dasmErrorCmp ( SHORT sId, T_err_comp *errCmp, BOOL is_fac_ussd  )
+{
+  TRACE_EVENT_P1("psaSS_dasmErrorCmp: errCmp: %02x",errCmp -> err_code);
+
+  if( errCmp -> v_err_code )
+  {
+    ssShrdPrm.stb[sId].failType = SSF_SS_ERR;
+    ssShrdPrm.stb[sId].errCd    = errCmp -> err_code;
+
+    
+    switch(errCmp -> err_code)
+    {
+      case ERR_PWD_REG_FAIL:
+        if( errCmp -> v_params AND errCmp -> params.l_params )
+        {  
+          T_PW_REGISTRATION_FAILURE_ERR *pwRegFail; 
+            
+          pwRegFail = (T_PW_REGISTRATION_FAILURE_ERR *)errCmp -> params.b_params;
+
+          TRACE_EVENT_P1("VGK:Error reported %d", errCmp -> err_code);
+          TRACE_EVENT_P1("VGK:Error params %d", pwRegFail->pwRegistrationFailureCause);
+
+          if (pwRegFail->v_pwRegistrationFailureCause)
+            ssShrdPrm.stb[sId].errPrms = pwRegFail->pwRegistrationFailureCause;
+        }
+        break;
+
+      default:
+        break;
+    }
+
+    /* check for protocol incompatibility for USSD */
+    if( is_fac_ussd                                 AND
+        errCmp -> err_code EQ ERR_FAC_NOT_SUPPORTED )
+    {
+      if( psaSS_asmUSSDProt1(sId) )
+      {
+        return( AT_CMPL );
+      }
+    }
+    
+  }
+  return( AT_FAIL );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_dasmRejectCmp     |
++-------------------------------------------------------------------+
+
+  PURPOSE : disassemble the error component.
+*/
+
+GLOBAL T_ACI_RETURN psaSS_dasmRejectCmp ( SHORT sId, T_rej_comp *rejCmp, BOOL is_fac_ussd  )
+{
+  TRACE_FUNCTION("psaSS_dasmRejectCmp");
+
+  if( rejCmp -> v_gen_problem )
+  {
+    ssShrdPrm.stb[sId].failType = SSF_GEN_PRB;
+    ssShrdPrm.stb[sId].rejPrb   = rejCmp -> gen_problem;
+  }
+
+  else if( rejCmp -> v_inv_problem )
+  {
+    ssShrdPrm.stb[sId].failType = SSF_INV_PRB;
+    ssShrdPrm.stb[sId].rejPrb   = rejCmp -> inv_problem;
+
+    /* check for protocol incompatibility for USSD */
+    if( is_fac_ussd                                  AND
+        rejCmp -> inv_problem EQ INV_PROB_UNRECOG_OP )
+    {
+      if( psaSS_asmUSSDProt1(sId) )
+      {
+        return( AT_CMPL );
+      }
+    }
+  }
+
+  else if( rejCmp -> v_res_problem )
+  {
+    ssShrdPrm.stb[sId].failType = SSF_RSL_PRB;
+    ssShrdPrm.stb[sId].rejPrb   = rejCmp -> res_problem;
+  }
+
+  else if( rejCmp -> v_err_problem )
+  {
+    ssShrdPrm.stb[sId].failType = SSF_ERR_PRB;
+    ssShrdPrm.stb[sId].rejPrb   = rejCmp -> err_problem;
+  }
+  return( AT_FAIL );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SATF                |
+|                                 ROUTINE : psaSAT_ss_end_ind       |
++-------------------------------------------------------------------+
+
+  PURPOSE : handles responses to user after a SS.
+            is_fac_ussd TRUE if facility is a USSD
+*/
+
+GLOBAL T_ACI_RETURN psaSS_ss_end_ind ( SHORT sId, T_COMPONENT *com, BOOL is_fac_ussd )
+{
+  if( com->v_res_comp )
+  {
+    psaSS_dasmResultCmp( sId, &com->res_comp );
+    return( AT_EXCT );
+  }
+  
+  if( com->v_err_comp )
+  {
+    return(psaSS_dasmErrorCmp( sId, &com->err_comp, is_fac_ussd ));
+  }
+
+  if( com->v_rej_comp )
+  {
+    return(psaSS_dasmRejectCmp( sId, &com->rej_comp, is_fac_ussd ));
+  }
+  
+  TRACE_EVENT( "WRONG COMPONENT TYPE RECEIVED" );
+  return(AT_FAIL);
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_stbNewEntry       |
++-------------------------------------------------------------------+
+
+  PURPOSE : returns the service table index for a free entry to be
+            used, otherwise the function returns -1 to indicate that
+            no entry is free.
+*/
+
+GLOBAL SHORT psaSS_stbNewEntry ( void )
+{
+  SHORT stbIdx;             /* holds service table index */
+
+  for( stbIdx = 0; stbIdx < MAX_SS_NR; stbIdx++ )
+  {
+    if( (ssShrdPrm.stb[stbIdx].ntryUsdFlg EQ FALSE) OR
+        (ssShrdPrm.stb[stbIdx].srvStat    EQ SSS_IDL)    )
+    {
+      psaSS_InitStbNtry( stbIdx );
+
+      return( stbIdx );
+    }
+  }
+
+  return( -1 );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_stbFindTi         |
++-------------------------------------------------------------------+
+
+  PURPOSE : returns the service table index for the entry that holds
+            service parameters for the passed transaction identifier.
+            Returning -1 indicates that the passed ti was not found.
+*/
+
+GLOBAL SHORT psaSS_stbFindTi ( UBYTE ti2Find )
+{
+  SHORT stbIdx;             /* holds service table index */
+
+  for( stbIdx = 0; stbIdx < MAX_SS_NR; stbIdx++ )
+  {
+    if( ssShrdPrm.stb[stbIdx].ti EQ ti2Find )
+
+      return( stbIdx );
+  }
+
+  return( -1 );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_stbFindInvId      |
++-------------------------------------------------------------------+
+
+  PURPOSE : returns the service table index for the entry that holds
+            service parameters for the passed invoke id.
+            Returning -1 indicates that the passed ti was not found.
+*/
+
+GLOBAL SHORT psaSS_stbFindInvId ( UBYTE iId2Find )
+{
+  SHORT stbIdx;             /* holds service table index */
+
+  for( stbIdx = 0; stbIdx < MAX_SS_NR; stbIdx++ )
+  {
+    if( ssShrdPrm.stb[stbIdx].ntryUsdFlg EQ TRUE AND
+        ssShrdPrm.stb[stbIdx].iId        EQ iId2Find )
+
+      return( stbIdx );
+  }
+
+  return( -1 );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_chgSrvTypCnt      |
++-------------------------------------------------------------------+
+
+  PURPOSE : this function modifies the service type counter (MOS/MTS)
+            defined by the passed service id by the passed delta value.
+*/
+
+GLOBAL void psaSS_chngSrvTypCnt ( SHORT sId, SHORT dlt )
+{
+
+  switch( ssShrdPrm.stb[sId].srvType )
+  {
+    case( ST_MOS ):
+
+      ssShrdPrm.nrOfMOS += dlt;
+
+      if( ssShrdPrm.nrOfMOS < 0 ) ssShrdPrm.nrOfMOS = 0;
+
+      break;
+
+    case( ST_MTS ):
+
+      ssShrdPrm.nrOfMTS += dlt;
+
+      if( ssShrdPrm.nrOfMTS < 0 ) ssShrdPrm.nrOfMTS = 0;
+
+      break;
+
+    default:
+
+      TRACE_EVENT( "UNEXP SERVICE TYPE IN STB" );
+  }
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_getMOSTi          |
++-------------------------------------------------------------------+
+
+  PURPOSE : this function selects a ti out of a pool of valid ti's
+            and inserts it into the passed service table entry. if no
+            ti is available the function returns -1.
+            a bit of the pool stands for a valid ti.
+            0 indicates a used ti, 1 indicates a free ti.
+*/
+
+GLOBAL SHORT psaSS_getMOSTi( SHORT sId )
+{
+  UBYTE idx;               /* holds pool idx */
+
+  for( idx = 0; idx < MAX_MOSTI_NR; idx++ )
+  {
+    if( tiPool & (1u << idx) )
+    {
+      tiPool &= ~(1u << idx);
+      ssShrdPrm.stb[sId].ti = idx;
+      return( 0 );
+    }
+  }
+  return( -1 );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_retMOSTi          |
++-------------------------------------------------------------------+
+
+  PURPOSE : this function returns a used ti to the ti pool if the
+            call was a MOS. the ti is free for the next MOS
+            afterwards.
+            a bit of the pool stands for a valid ti.
+            0 indicates a used ti, 1 indicates a free ti.
+*/
+
+GLOBAL void psaSS_retMOSTi( SHORT sId )
+{
+  if( ssShrdPrm.stb[sId].srvType EQ ST_MOS )
+
+    if( ssShrdPrm.stb[sId].ti < MAX_MOSTI_NR )
+
+      tiPool |= (0x01 << ssShrdPrm.stb[sId].ti);
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SS                  |
+|                                 ROUTINE : psaSS_InitStbNtry       |
++-------------------------------------------------------------------+
+
+  PURPOSE : initialize the indexed service table entry.
+
+*/
+
+GLOBAL void psaSS_InitStbNtry ( SHORT idx )
+{
+
+/*
+ *-------------------------------------------------------------------
+ * initialize call table entry
+ *-------------------------------------------------------------------
+ */
+  ssShrdPrm.stb[idx].ntryUsdFlg   = FALSE;
+  ssShrdPrm.stb[idx].ti           = NO_ENTRY;
+  ssShrdPrm.stb[idx].iId          = 0;
+  ssShrdPrm.stb[idx].srvStat      = NO_VLD_SSS;
+  ssShrdPrm.stb[idx].srvType      = NO_VLD_ST;
+  ssShrdPrm.stb[idx].orgOPC       = NOT_PRESENT_8BIT;
+  ssShrdPrm.stb[idx].opCode       = NOT_PRESENT_8BIT;
+  ssShrdPrm.stb[idx].ssCode       = NOT_PRESENT_8BIT;
+  ssShrdPrm.stb[idx].ussdReqFlg   = FALSE;
+  ssShrdPrm.stb[idx].failType     = NO_VLD_SSF;
+  ssShrdPrm.stb[idx].entCs        = NOT_PRESENT_16BIT;
+  ssShrdPrm.stb[idx].rejPrb       = NOT_PRESENT_8BIT;
+  ssShrdPrm.stb[idx].errCd        = NOT_PRESENT_8BIT;
+  ssShrdPrm.stb[idx].errPrms      = NOT_PRESENT_8BIT;
+  ssShrdPrm.stb[idx].curCmd       = AT_CMD_NONE;
+  ssShrdPrm.stb[idx].srvOwn       = OWN_NONE;
+  ssShrdPrm.stb[idx].SSver        = DEF_SS_VER;
+  ssShrdPrm.stb[idx].ussd_operation = FALSE;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_stbFindUssdReq    |
++-------------------------------------------------------------------+
+
+  PURPOSE : returns the service table index for the entry that has a
+            USSD request pending.
+            Returning -1 indicates that no such service was found.
+*/
+
+GLOBAL SHORT psaSS_stbFindUssdReq ( void )
+{
+  SHORT stbIdx;             /* holds call table index */
+
+  for( stbIdx = 0; stbIdx < MAX_SS_NR; stbIdx++ )
+  {
+    if( ssShrdPrm.stb[stbIdx].ntryUsdFlg EQ TRUE    AND
+        ssShrdPrm.stb[stbIdx].ussdReqFlg EQ TRUE    AND
+        ssShrdPrm.stb[stbIdx].srvStat    EQ SSS_ACT )
+    {
+          return( stbIdx );
+    }
+  }
+
+  return( -1 );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_stbFindActSrv     |
++-------------------------------------------------------------------+
+
+  PURPOSE : returns the service table index for the first entry that
+            holds an active service which is not the passed index.
+            Returning -1 indicates that no active service was found.
+*/
+
+GLOBAL SHORT psaSS_stbFindActSrv ( SHORT sId )
+{
+  SHORT stbIdx;             /* holds call table index */
+
+  for( stbIdx = 0; stbIdx < MAX_SS_NR; stbIdx++ )
+  {
+    if( ssShrdPrm.stb[stbIdx].ntryUsdFlg EQ TRUE    AND
+        ssShrdPrm.stb[stbIdx].srvStat    EQ SSS_ACT )
+    {
+      if( stbIdx NEQ sId )
+
+        return( stbIdx );
+    }
+  }
+
+  return( -1 );
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SS                  |
+|                                 ROUTINE : psaSS_Init              |
++-------------------------------------------------------------------+
+
+  PURPOSE : initialize the protocol stack adapter for SS.
+
+*/
+
+GLOBAL void psaSS_Init ( void )
+{
+  UBYTE stbIdx;            /* holds index to service table */
+
+/*
+ *-------------------------------------------------------------------
+ * initialize service table
+ *-------------------------------------------------------------------
+ */
+  for( stbIdx = 0; stbIdx < MAX_SS_NR; stbIdx++ )
+  {
+    psaSS_InitStbNtry( stbIdx );
+  }
+
+ /*
+  *-------------------------------------------------------------------
+  * initialize shared parameter
+  *-------------------------------------------------------------------
+  */
+  ssShrdPrm.nrOfMOS = 0;
+  ssShrdPrm.nrOfMTS = 0;
+  ssShrdPrm.iIdNxt  = 0;
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SS                  |
+|                                 ROUTINE : psaSS_DumpFIE           |
++-------------------------------------------------------------------+
+
+  PURPOSE : Dump facility information element to debug output.
+
+*/
+
+GLOBAL void psaSS_DumpFIE ( T_fac_inf * fie )
+{
+
+  CHAR  strBuf[40+1];           /* holds string buffer */
+  UBYTE idx, cnt, mcnt;         /* buffer index */
+  CHAR  *pDest;                 /* points to destination */
+
+/*
+ *-------------------------------------------------------------------
+ * format FIE
+ *-------------------------------------------------------------------
+ */
+  TRACE_EVENT( "FIE SENT/RECEIVED:" );
+
+  mcnt = fie->l_fac >> 3;
+
+  if( mcnt EQ 0 )
+  {
+    TRACE_EVENT("Empty Facility");
+    return;
+  }
+
+  for( cnt = 0; cnt < mcnt; cnt+=idx )
+  {
+    pDest = strBuf;
+
+    for( idx = 0; idx < 20 AND idx+cnt < mcnt; idx++ )
+    {
+      pDest += sprintf( pDest, "%02X", (UBYTE)fie->fac[idx+cnt] );
+    }
+
+    *pDest = 0x0;
+
+    TRACE_EVENT( strBuf );
+  }
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_stbDump           |
++-------------------------------------------------------------------+
+
+  PURPOSE : this function dumps the service table to the debug output.
+*/
+
+GLOBAL void psaSS_stbDump ( void )
+{
+#ifdef TRACING
+
+  SHORT stbIdx;                             /* holds service table index */
+  char  lnBuf[HDR_WDT+(MAX_ITM*ITM_WDT)+1]; /* holds buffer for output line */
+  char  verBuf[VERSION_LEN+1];              /* holds buffer for SS version */
+  SHORT itmIdx;                             /* holds items per line index */
+  SHORT chrNr;                              /* holds number of processed chars */
+
+  for( stbIdx = 0; stbIdx < MAX_SS_NR; stbIdx+=MAX_ITM )
+  {
+    /* --- service id ----------------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "   srv id");
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx+stbIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*d", ITM_WDT, stbIdx + itmIdx );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- entry used flag -----------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "entry used" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*hd", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].ntryUsdFlg );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- transaction identifier ----------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "        ti" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*hd", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].ti );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- service status ------------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "srv status" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*hd", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].srvStat );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- service type --------------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "  srv type" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*hd", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].srvType );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- SS version ----------------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "SS version" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*d", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].SSver );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- failure type ------------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "fail. type" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*d", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].failType );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- entity cause ------------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "ent. cause" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*d", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].entCs );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- reject problem ----------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, " rej. prob" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*hd", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].rejPrb );
+    }
+    TRACE_EVENT( lnBuf );
+
+    /* --- error code ----------------------------------------------------*/
+    chrNr = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, " err. code" );
+
+    for( itmIdx = 0; (itmIdx<MAX_ITM)AND(itmIdx<MAX_SS_NR); itmIdx++ )
+    {
+      chrNr += sprintf( lnBuf+chrNr, "%*hd", ITM_WDT,
+                        ssShrdPrm.stb[stbIdx+itmIdx].errCd );
+    }
+    TRACE_EVENT( lnBuf );
+
+  }
+
+#endif  /* of #ifdef TRACING */
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : PSA_SSF                 |
+|                                 ROUTINE : psaSS_shrPrmDump        |
++-------------------------------------------------------------------+
+
+  PURPOSE : this function dumps the shared parameter to the debug
+            output.
+*/
+
+GLOBAL void psaSS_shrPrmDump ( void )
+{
+#ifdef TRACING
+
+  char  lnBuf[80];              /* holds buffer for output line */
+  SHORT chrNr;                  /* holds number of processed chars */
+
+  /* --- nr of MOSs -----------------------------------------------*/
+  chrNr  = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "nr. of MOS" );
+  chrNr += sprintf( lnBuf+chrNr, "%*d", ITM_WDT,
+                                        ssShrdPrm.nrOfMOS );
+  TRACE_EVENT( lnBuf );
+
+  /* --- nr of MTSs -----------------------------------------------*/
+  chrNr  = sprintf( lnBuf, "%*.*s", HDR_WDT, HDR_WDT, "nr. of MTS" );
+  chrNr += sprintf( lnBuf+chrNr, "%*d", ITM_WDT,
+                                        ssShrdPrm.nrOfMTS );
+  TRACE_EVENT( lnBuf );
+
+#endif  /* of #ifdef TRACING */
+}
+
+/*
++-------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CMH_F                   |
+|                                 ROUTINE : psaSS_GetPendingTrn     |
++-------------------------------------------------------------------+
+
+  PURPOSE : Find Id of a pending call for multy-transaction operation
+
+*/
+
+GLOBAL SHORT psaSS_GetPendingTrn ( void )
+{
+  SHORT bit_len;
+  SHORT i;
+
+  bit_len = 8 * sizeof(ssShrdPrm.mltyTrnFlg);
+  for (i = 0; i < bit_len; i++)
+  {
+    if ( ssShrdPrm.mltyTrnFlg & ( 0x1 << i ) )
+      return i;
+  }
+
+  return -1;
+}
+
+GLOBAL void psaSS_KillAllPendingTrn ( void ) /* sId: main transaction: not to be killed */
+{
+  SHORT          pending_idx;
+
+  TRACE_FUNCTION("psaSS_KillAllPendingTrn( )");
+
+  while ( ssShrdPrm.mltyTrnFlg )
+  {
+    pending_idx = psaSS_GetPendingTrn( );
+    ssShrdPrm.mltyTrnFlg &= ~( 1u << pending_idx );  /* unsent id flag */
+
+    ssShrdPrm.stb[ pending_idx ].ntryUsdFlg = FALSE;  /* free entry in ss table */
+    ssShrdPrm.stb[ pending_idx ].srvStat = NO_VLD_SSS; /* not sure if it's necessary...? */
+
+    PFREE( ssShrdPrm.stb[pending_idx].save_prim ); /* free pending primitive */
+  }
+}
+
+/*==== EOF ========================================================*/
+