/*=============================================================================
FILE:  OEMTSUPPS.c

SERVICES:  OEM functions for supporting BREW SUPPS Interface

GENERAL DESCRIPTION:
  This file provides the prorotypes of the functions that OEMs must
  provide in order to support the BREW ISuppsTrans interface.

PUBLIC CLASSES AND STATIC FUNCTIONS:

      OEMSUPPS_AddRef            Adds a brew reference to the SUPPS object.
      OEMSUPPS_Release           Removes a brew reference to the SUPPS object.
      OEMSUPPS_QueryInterface    Returns a new interface, not yet supported.
      OEMSupps_ParseString       Checks if a string is a SS command.
      OEMSUPPS_LoadMessage       
      OEMSUPPS_Run               
      OEMSUPPS_GetResult         

        Copyright © 2004 QUALCOMM Incorporated.
               All Rights Reserved.
            QUALCOMM Proprietary/GTDR

=============================================================================*/
/*=============================================================================

$Header: //brewery/rel/3.1.2pk/pk/src/msm/OEMTSupps.c#1 $

                      EDIT HISTORY FOR FILE

This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.

when       who     what, where, why
--------   ---     ----------------------------------------------------------
05/01/03    at     Initial release.
=============================================================================*/
/*lint -esym(754, ISuppsTrans::pvt) */
/*lint -esym(754, ISuppsTrans_Notifier::pvt) */

#include "OEMFeatures.h"

#include "AEE.h"         // BREW headers.
#include "AEEStdlib.h"
#include "AEE_OEM.h"     // Brew OEM Headers.
#include "AEETelephone.h"  // Header file for SUPPS interface
#include "AEECriticalSection.h" 
#include "OEMTelephone.h"

#include "cm.h"
#ifdef AEE_SIMULATOR
#include "cm/cmi.h"
#else
#include "cmutil.h"
#endif

#ifdef FEATURE_MMGSDI
#include "gsdi_exp.h"
#endif


#ifdef MSG_ERROR 
   #undef MSG_ERROR
#endif
#ifdef MSG_HIGH
   #undef MSG_HIGH
#endif
#ifdef MSG_MED
   #undef MSG_MED
#endif
#ifdef MSG_LOW
   #undef MSG_LOW
#endif

#define FARF_OEMTSUPPS_ERROR   1
#define FARF_OEMTSUPPS_HIGH    1
#define FARF_OEMTSUPPS_MED     0
#define FARF_OEMTSUPPS_LOW     0

#ifdef FARF
#undef FARF
#endif /* #ifdef FARF */

#define FARF(x, p)  if (1 == FARF_##x) DBGPRINTF p 


#define MSG_ERROR( sf, a, b, c )    FARF(OEMTSUPPS_ERROR, (sf, a, b, c))
#define MSG_HIGH( sf, a, b, c )     FARF(OEMTSUPPS_HIGH, (sf, a, b, c))
#define MSG_MED( sf, a, b, c )      FARF(OEMTSUPPS_MED, (sf, a, b, c))
#define MSG_LOW( sf, a, b, c )      FARF(OEMTSUPPS_LOW, (sf, a, b, c))

#ifndef INRANGE
#define INRANGE( val, min, max )  ( (val) >= (min) && (val) <= (max) )
#endif

#define OEMSUPPS_MAX_BSG_LEN            2
#define OEMSUPPS_MAX_SC_LEN             3
#define OEMSUPPS_MAX_SIA_LEN            20  /*   */
#define OEMSUPPS_MAX_SIB_LEN            4   /* PWD LEN */
#define OEMSUPPS_MAX_SIC_LEN            4   /* PWD LEN */
#define OEMSUPPS_MAX_TEXT_LEN           50
#define OEMSUPPS_MAX_FWD_TO_NUMBER      20
#define OEMSUPPS_CUG_SIZE                2  /*Max Number of CUG Indicators*/

#define OEMSUPPS_MAX_BCD_PHONE_NUM_LEN  27
#define OEMSUPPS_MAX_SUBADDRESS_LEN     22
#define OEMSUPPS_MAX_BC_LEN             8
#define OEMSUPPS_MAX_PIN_LEN            (8+1)
#define OEMSUPPS_MAX_PUK_LEN            (8+1)

#define OEMSUPPS_DEFAULT_ALPHABET                 0x00
#define OEMSUPPS_ALPHABET_MASK                    0xF0
#define OEMSUPPS_USS_DEF_ALPHABET_LANG_UNSPEC     0x0F

#define AEETSUPPS_BM(val) (val << 16)

#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)
/*lint -save -e701*/
/*lint -save -e749*/
/*lint -save -e750*/
typedef enum
{
   OEMSUPPS_ALL_SERVICES                 =0x00 |(AEETSUPPS_BM(NO_CODE)),
/*
** BEARER-SERVICES
*/
  OEMSUPPS_ALL_BEARER_SERVICES           =0x00 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_DATA_CDA_SERVICES         =0x10 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDA_300BPS               =0x11 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDA_1200BPS              =0x12 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDA_1200_75BPS           =0x13 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDA_2400BPS              =0x14 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDA_4800BPS              =0x15 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDA_9600BPS              =0x16 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_DATA_CDS_SERVICES         =0x18 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDS_1200BPS              =0x1A |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDS_2400BPS              =0x1C |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDS_4800BPS              =0x1D |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_CDS_9600BPS              =0x1E |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_PAD_ACCESS_CA_SERVICES    =0x20 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PAD_ACCESS_CA_300BPS          =0x21 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PAD_ACCESS_CA_1200BPS         =0x22 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PAD_ACCESS_CA_1200_75BPS      =0x23 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PAD_ACCESS_CA_2400BPS         =0x24 |(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PAD_ACCESS_CA_4800BPS         =0x25|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PAD_ACCESS_CA_9600BPS         =0x26|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_DATA_PDS_SERVICES         =0x28|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_PDS_2400BPS              =0x2C|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_PDS_4800BPS              =0x2D|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_DATA_PDS_9600BPS              =0x2E|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_ALTERNATE_SPEECH_DATA_CDA =0x30|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_ALTERNATE_SPEECH_DATA_CDS =0x38|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_SPEECH_FOLLWOED_BYDATA_CDA=0x40|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_SPEECH_FOLLWOED_BYDATA_CDS=0x48|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_DATA_CIRCUIT_ASYNCHRONOUS =0x50|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_DATA_CIRCUIT_SYNCHRONOUS  =0x58|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_ASYNCHRONOUS_SERVICES     =0x60|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_SYNCHRONOUS_SERVICES      =0x68|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_ALL_PLMN_SPECIFIC_BS          =0xD0|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_1            =0xD1|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_2            =0xD2|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_3            =0xD3|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_4            =0xD4|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_5            =0xD5|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_6            =0xD6|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_7            =0xD7|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_8            =0xD8|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_9            =0xD9|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_A            =0xDA|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_B            =0xDB|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_C            =0xDC|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_D            =0xDD|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_E            =0xDE|(AEETSUPPS_BM(BS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_BS_F            =0xDF|(AEETSUPPS_BM(BS_CODE)),

  OEMSUPPS_ALL_TELESERVICES               =0x0 |(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_ALL_SPEECH_TRANSMISSION_SERVCES=0x10|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_TELEPHONY                      =0x11|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_EMERGENCY_CALLS                =0x12|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_ALL_SMS_SERVICES               =0x20|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_SHORT_MSG_MT_PP                =0x21|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_SHORT_MSG_MO_PP                =0x22|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_ALL_FAX_TRANSMISSION_SERVICES  =0x60|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_FAX_GROUP3_AND_ALTER_SPEECH    =0x61|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_AUTO_FAX_GROUP3                =0x62|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_FAX_GROUP4                     =0x63|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_ALL_DATA_TELESERVICES          =0x70|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_ALL_TELESERVICES_EXCEPT_SMS    =0x80|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_ALL_PLMN_SPECIFIC_TS           =0xD0|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_1             =0xD1|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_2             =0xD2|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_3             =0xD3|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_4             =0xD4|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_5             =0xD5|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_6             =0xD6|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_7             =0xD7|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_8             =0xD8|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_9             =0xD9|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_A             =0xDA|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_B             =0xDB|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_C             =0xDC|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_D             =0xDD|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_E             =0xDE|(AEETSUPPS_BM(TS_CODE)),
  OEMSUPPS_PLMN_SPECIFIC_TS_F             =0xDF|(AEETSUPPS_BM(TS_CODE))

}OEMSUPPSBasicService;
#endif /* FEATURE_WCDMA || FEATURE_GSM */



#define AEETSUPPS_IS_ALL_CF(x)  ( (x & 0xF0 )== AEETSUPPS_CODE_ALL_FORWARDING_SS ? TRUE: FALSE)
#define AEETSUPPS_IS_RSTRCT(x)  ( (x & 0xF0 )== AEETSUPPS_CODE_ALL_CALL_RSTRCT_SS ? TRUE: FALSE)

#define AEETSUPPS_IS_CF(x)                                                      \
                          ( ((x) == AEETSUPPS_CODE_ALL_CALL_RSTRCT_SS   ||      \
                             (x) == AEESUPPSVC_ALL_CONDFWD_SS  ||               \
                             (x) == AEESUPPSVC_CFNRY)                           \
                             ? TRUE : FALSE )


/*Type of Supplementary Service Operations*/
typedef struct
{
  char *sups_operation;
  AEETSuppsRequestType op_code;
} OEMSUPPS_OPERATION;

OEMSUPPS_OPERATION OEMSUPPS_operation_input[] =
{
  {"**", AEETSUPPS_REQ_REGISTER},
  {"*#", AEETSUPPS_REQ_INTERROGATE},
  {"*",  AEETSUPPS_REQ_ACTIVATE},
  {"##", AEETSUPPS_REQ_ERASE},
  {"#",  AEETSUPPS_REQ_DEACTIVATE},
  { NULL, NULL}
};

static cm_client_id_type client_sups;

typedef struct
{
   char * local_sc;         /* local value of SC */
   byte   net_sc;           /* Network SC */
} OEMSUPPSSCTableType;


/*
** Local Supplementary Service Codes (SC)
*/
#define OEMSUPPS_LOCAL_SC_ALL               ""
#define OEMSUPPS_LOCAL_SC_CF                "002"
#define OEMSUPPS_LOCAL_SC_CFC               "004"
#define OEMSUPPS_LOCAL_SC_CFU               "21"
#define OEMSUPPS_LOCAL_SC_CFB               "67"
#define OEMSUPPS_LOCAL_SC_CFNRY             "61"
#define OEMSUPPS_LOCAL_SC_CFNRC             "62"
#define OEMSUPPS_LOCAL_SC_CLIP              "30"
#define OEMSUPPS_LOCAL_SC_CLIR              "31"
#define OEMSUPPS_LOCAL_SC_COLP              "76"
#define OEMSUPPS_LOCAL_SC_COLR              "77"
#define OEMSUPPS_LOCAL_SC_CW                "43"
#define OEMSUPPS_LOCAL_SC_CNAP              "300"
#define OEMSUPPS_LOCAL_SC_B                 "330"
#define OEMSUPPS_LOCAL_SC_OB                "333"
#define OEMSUPPS_LOCAL_SC_IB                "353"
#define OEMSUPPS_LOCAL_SC_BAOC              "33"
#define OEMSUPPS_LOCAL_SC_BOIC              "331"
#define OEMSUPPS_LOCAL_SC_BOICEXHC          "332"
#define OEMSUPPS_LOCAL_SC_BAIC              "35"
#define OEMSUPPS_LOCAL_SC_BICROAM           "351"
#define OEMSUPPS_LOCAL_BSG_REG_PASSWD       "03"

#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)
/*Local to Network Mapping*/
const OEMSUPPSSCTableType OEMSUPPSSCConversionTable [] =
{
   { OEMSUPPS_LOCAL_SC_ALL,        all_ss },
   { OEMSUPPS_LOCAL_SC_CF,         allForwardingSS },
   { OEMSUPPS_LOCAL_SC_CFC,        allCondForwardingSS },
   { OEMSUPPS_LOCAL_SC_CFU,        cfu },
   { OEMSUPPS_LOCAL_SC_CFB,        cfb },
   { OEMSUPPS_LOCAL_SC_CFNRY,      cfnry },
   { OEMSUPPS_LOCAL_SC_CFNRC,      cfnrc },
   { OEMSUPPS_LOCAL_SC_CLIP,       clip },
   { OEMSUPPS_LOCAL_SC_CLIR,       clir },
   { OEMSUPPS_LOCAL_SC_COLP,       colp },
   { OEMSUPPS_LOCAL_SC_COLR,       colr },
   { OEMSUPPS_LOCAL_SC_CW,         cw },
   { OEMSUPPS_LOCAL_SC_B,          allCallRestrictionSS },
   { OEMSUPPS_LOCAL_SC_OB,         barringOfOutgoingCalls },
   { OEMSUPPS_LOCAL_SC_IB,         barringOfIncomingCalls },
   { OEMSUPPS_LOCAL_SC_BAOC,       baoc },
   { OEMSUPPS_LOCAL_SC_BOIC,       boic },
   { OEMSUPPS_LOCAL_SC_BOICEXHC,   boicExHC },
   { OEMSUPPS_LOCAL_SC_BAIC,       baic },
   { OEMSUPPS_LOCAL_SC_BICROAM,    bicRoam },
   { OEMSUPPS_LOCAL_SC_CNAP,       cnap }
};
#endif /* FEATURE_WCDMA || FEATURE_GSM */

/*
** LOCAL Basic Service Codes
*/

#define OEMSUPPS_LOCAL_BSG_ALL              ""
#define OEMSUPPS_LOCAL_BSG_ALL_TS           "10"
#define OEMSUPPS_LOCAL_BSG_TELEPHONY        "11"
#define OEMSUPPS_LOCAL_BSG_ALL_DATA         "12"
#define OEMSUPPS_LOCAL_BSG_FAX              "13"
#define OEMSUPPS_LOCAL_BSG_SMS              "16"
#define OEMSUPPS_LOCAL_BSG_ALL_TELE_EX_SMS  "19"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_ALL    "50"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_1      "51"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_2      "51"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_3      "53"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_4      "54"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_5      "55"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_6      "56"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_7      "57"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_8      "58"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_9      "59"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_A      "60"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_B      "61"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_C      "62"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_D      "63"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_E      "64"
#define OEMSUPPS_LOCAL_BSG_PLMN_TELE_F      "65"

#define OEMSUPPS_LOCAL_BSG_ALL_BS           "20"
#define OEMSUPPS_LOCAL_BSG_ALL_ASYNC        "21"
#define OEMSUPPS_LOCAL_BSG_ALL_SYNC         "22"
#define OEMSUPPS_LOCAL_BSG_ALL_DC_SYNC      "24"
#define OEMSUPPS_LOCAL_BSG_ALL_DC_ASYNC     "25"
#define OEMSUPPS_LOCAL_BSG_ALL_DED_PACKET   "26"
#define OEMSUPPS_LOCAL_BSG_ALL_DED_PAD      "27"
#define OEMSUPPS_LOCAL_BSG_12_KBIT          "29"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_ALL    "70"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_1      "71"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_2      "71"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_3      "73"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_4      "74"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_5      "75"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_6      "76"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_7      "77"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_8      "78"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_9      "79"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_A      "80"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_B      "81"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_C      "82"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_D      "83"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_E      "84"
#define OEMSUPPS_LOCAL_BSG_PLMN_BEAR_F      "85"

#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)

typedef struct
{
   char   *local_bsg;       /* local BSG value */
   int   net_bsg_code;     /* network BSG value */
} OEMSUPPSStrBSGTableType;

#define OEMSUPPS_MAX_ENTRY (sizeof(OEMSUPPSSCConversionTable)/sizeof(OEMSUPPSSCTableType))
/*Local to Network Mapping*/

const OEMSUPPSStrBSGTableType OEMSUPPSStrBSGConversionTable[] = {
   { OEMSUPPS_LOCAL_BSG_ALL,             OEMSUPPS_ALL_SERVICES },
   { OEMSUPPS_LOCAL_BSG_ALL_TS,          OEMSUPPS_ALL_TELESERVICES},
   { OEMSUPPS_LOCAL_BSG_TELEPHONY,       OEMSUPPS_ALL_SPEECH_TRANSMISSION_SERVCES},
   { OEMSUPPS_LOCAL_BSG_ALL_DATA,        OEMSUPPS_ALL_DATA_TELESERVICES},
   { OEMSUPPS_LOCAL_BSG_FAX,             OEMSUPPS_ALL_FAX_TRANSMISSION_SERVICES},
   { OEMSUPPS_LOCAL_BSG_SMS,             OEMSUPPS_ALL_SMS_SERVICES},
   { OEMSUPPS_LOCAL_BSG_ALL_TELE_EX_SMS, OEMSUPPS_ALL_TELESERVICES_EXCEPT_SMS},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_ALL,   OEMSUPPS_ALL_PLMN_SPECIFIC_TS},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_1,     OEMSUPPS_PLMN_SPECIFIC_TS_1},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_2,     OEMSUPPS_PLMN_SPECIFIC_TS_2 },
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_3,     OEMSUPPS_PLMN_SPECIFIC_TS_3},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_4,     OEMSUPPS_PLMN_SPECIFIC_TS_4},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_5,     OEMSUPPS_PLMN_SPECIFIC_TS_5},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_6,     OEMSUPPS_PLMN_SPECIFIC_TS_6},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_7,     OEMSUPPS_PLMN_SPECIFIC_TS_7},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_8,     OEMSUPPS_PLMN_SPECIFIC_TS_8},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_9,     OEMSUPPS_PLMN_SPECIFIC_TS_9},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_A,     OEMSUPPS_PLMN_SPECIFIC_TS_A},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_B,     OEMSUPPS_PLMN_SPECIFIC_TS_B},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_C,     OEMSUPPS_PLMN_SPECIFIC_TS_C},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_D,     OEMSUPPS_PLMN_SPECIFIC_TS_D},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_E,     OEMSUPPS_PLMN_SPECIFIC_TS_E},
   { OEMSUPPS_LOCAL_BSG_PLMN_TELE_F,     OEMSUPPS_PLMN_SPECIFIC_TS_F},
   { OEMSUPPS_LOCAL_BSG_ALL_BS,          OEMSUPPS_ALL_BEARER_SERVICES},
   { OEMSUPPS_LOCAL_BSG_ALL_ASYNC,       OEMSUPPS_ALL_ASYNCHRONOUS_SERVICES},
   { OEMSUPPS_LOCAL_BSG_ALL_SYNC,        OEMSUPPS_ALL_SYNCHRONOUS_SERVICES},
   { OEMSUPPS_LOCAL_BSG_ALL_DC_SYNC,     OEMSUPPS_ALL_DATA_CIRCUIT_SYNCHRONOUS},
   { OEMSUPPS_LOCAL_BSG_ALL_DC_ASYNC,    OEMSUPPS_ALL_DATA_CIRCUIT_ASYNCHRONOUS},
   { OEMSUPPS_LOCAL_BSG_ALL_DED_PACKET,  OEMSUPPS_ALL_DATA_PDS_SERVICES},
   { OEMSUPPS_LOCAL_BSG_ALL_DED_PAD,     OEMSUPPS_ALL_PAD_ACCESS_CA_SERVICES},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_ALL,   OEMSUPPS_ALL_PLMN_SPECIFIC_BS},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_1,     OEMSUPPS_PLMN_SPECIFIC_BS_1 },
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_2,     OEMSUPPS_PLMN_SPECIFIC_BS_2 },
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_3,     OEMSUPPS_PLMN_SPECIFIC_BS_3},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_4,     OEMSUPPS_PLMN_SPECIFIC_BS_4},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_5,     OEMSUPPS_PLMN_SPECIFIC_BS_5},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_6,     OEMSUPPS_PLMN_SPECIFIC_BS_6},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_7,     OEMSUPPS_PLMN_SPECIFIC_BS_7},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_8,     OEMSUPPS_PLMN_SPECIFIC_BS_8},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_9,     OEMSUPPS_PLMN_SPECIFIC_BS_9},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_A,     OEMSUPPS_PLMN_SPECIFIC_BS_A},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_B,     OEMSUPPS_PLMN_SPECIFIC_BS_B},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_C,     OEMSUPPS_PLMN_SPECIFIC_BS_C},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_D,     OEMSUPPS_PLMN_SPECIFIC_BS_D},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_E,     OEMSUPPS_PLMN_SPECIFIC_BS_E},
   { OEMSUPPS_LOCAL_BSG_PLMN_BEAR_F,     OEMSUPPS_PLMN_SPECIFIC_BS_F}
};

#define OEMSSUPPS_MAX_STR_BSG_ENTRY (sizeof(OEMSUPPSStrBSGConversionTable)/sizeof(OEMSUPPSStrBSGTableType))

/*AEE SC Code Mapping to Network Values*/
typedef struct
{
   int   local;   
   int   net_code;
} OEMSUPPSTableType;

const OEMSUPPSTableType OEMSUPPSBSGConversionTable[] = {
   { AEETSUPPS_BASIC_SERVICE_ALL,                      OEMSUPPS_ALL_SERVICES },
   { AEETSUPPS_BASIC_SERVICE_ALL_TELESERVICES,         OEMSUPPS_TELEPHONY} ,
   { AEETSUPPS_BASIC_SERVICE_ALL_TELESERVICES,         OEMSUPPS_ALL_TELESERVICES},
   { AEETSUPPS_BASIC_SERVICE_ALL_SPEECH_TRANSMISSION,  OEMSUPPS_ALL_SPEECH_TRANSMISSION_SERVCES},
   { AEETSUPPS_BASIC_SERVICE_ALL_FAX,                  OEMSUPPS_ALL_FAX_TRANSMISSION_SERVICES},
   { AEETSUPPS_BASIC_SERVICE_ALL_SMS,                  OEMSUPPS_ALL_SMS_SERVICES},
   { AEETSUPPS_BASIC_SERVICE_ALL_BEARER,               OEMSUPPS_ALL_BEARER_SERVICES},
   { AEETSUPPS_BASIC_SERVICE_ALL_ASYNCHRONOUS,         OEMSUPPS_ALL_ASYNCHRONOUS_SERVICES},
   { AEETSUPPS_BASIC_SERVICE_ALL_SYNCHRONOUS,          OEMSUPPS_ALL_SYNCHRONOUS_SERVICES}
   
};
#define OEMSSUPPS_MAX_BSG_ENTRY (sizeof(OEMSUPPSBSGConversionTable)/sizeof(OEMSUPPSTableType))

/*AEE SS Operation Mapping to Netowork Mapping*/
const OEMSUPPSTableType OEMSUPPSSSOperConversionTable[]=
{
  {AEETSUPPS_REQ_REGISTER,          registerSS},
  {AEETSUPPS_REQ_ERASE,             eraseSS},
  {AEETSUPPS_REQ_ACTIVATE,          activateSS},
  {AEETSUPPS_REQ_DEACTIVATE,        deactivateSS},
  {AEETSUPPS_REQ_INTERROGATE,       interrogateSS},
  {AEETSUPPS_REQ_REGISTER_PASSWD,   registerPassword},
  {AEETSUPPS_REQ_USS,               processUnstructuredSS_Data},
  {AEETSUPPS_IND_ENTER_PASSWD,      getPassword},
  {AEETSUPPS_IND_FWD_CHECK,         forwardCheckSS_Indication},
  {AEETSUPPS_IND_USS,               processUnstructuredSS_Request},
  {AEETSUPPS_IND_USS_NOTIFY,        processUnstructuredSS_Request}
};


#define OEMSSUPPS_MAX_OP_ENTRY (sizeof(OEMSUPPSSSOperConversionTable)/sizeof(OEMSUPPSTableType))

const OEMSUPPSTableType OEMSUPPSCMCmdConversionTable[]=
{
  {AEETSUPPS_REQ_REGISTER,          CM_SUPS_CMD_REGISTER},
  {AEETSUPPS_REQ_ERASE,             CM_SUPS_CMD_ERASE},
  {AEETSUPPS_REQ_ACTIVATE,          CM_SUPS_CMD_ACTIVATE},
  {AEETSUPPS_REQ_DEACTIVATE,        CM_SUPS_CMD_DEACTIVATE},
  {AEETSUPPS_REQ_INTERROGATE,       CM_SUPS_CMD_INTERROGATE},
  {AEETSUPPS_REQ_REGISTER_PASSWD,   CM_SUPS_CMD_REG_PASSWORD},
  {AEETSUPPS_IND_ENTER_PASSWD,      CM_SUPS_CMD_GET_PASSWORD_RES},
  {AEETSUPPS_IND_USS,               CM_SUPS_CMD_PROCESS_USS},
  {AEETSUPPS_IND_USS_NOTIFY,        CM_SUPS_CMD_USS_NOTIFY_RES}
};

#define OEMSSUPPS_MAX_CMD (sizeof(OEMSUPPSCMCmdConversionTable)/sizeof(OEMSUPPSTableType))
#endif /* FEATURE_WCDMA || FEATURE_GSM */

typedef struct OEMSUPPS_NOTIFIER_notify_cb
{
  uint32 mask;
  AEETSuppsEventData user_data;
} OEMSUPPS_NOTIFIER_NOTIFY_CB;



#define OEMSUPPS_MAX_CB    5        /* Max pending event callbacks */

static AEECriticalSection gcmCriticalSection;
#define OEMSUPPS_MUTEX_LOCK() AEECriticalSection_Enter(&gcmCriticalSection);
#define OEMSUPPS_MUTEX_UNLOCK() AEECriticalSection_Leave(&gcmCriticalSection);


/*EventCB used while switching from DMSS context to BREW*/
typedef struct OEMSUPPSEventCB {
  AEECallback          cb;         
  boolean              bInUse;
  int                  event;   /*CM Events or CM Errors*/
  void *               data;
  uint8                nRef;
  int                  cmd;
  int                  cmd_err;
} OEMSUPPSEventCB;

/* The following structure is for the SuppSvcobject when
 * it is allocated. */
struct ISuppsTrans
{
   IShell                     *m_pIShell;         /* Pointer to the IShell object. */
   uint32                     m_uRefs;           /* Number of references to this obj */
   AEETSuppsTransId           m_transId;           /* Index of current supplementary service in progress*/
   OEMSUPPSEventCB            m_evtcb[OEMSUPPS_MAX_CB];/*Event Callbacks*/
   AEETSuppsTransState        m_transState;
   AEETSuppsMessage           m_msg;
   AEETSuppsStatus            m_result;
#ifdef FEATURE_MMGSDI
   gsdi_pin_ids_T             m_pin;
#endif
   AEETSuppsTransId           m_InvokeId;
};


typedef struct {
   AEETSuppsMessage  *pMsg;
   uint32            dwExtra;
   uint32            dwNeeded;
} SuppsBuffer;



/*A string can be broken down on into a set of tokens based on the regular
  expression*/
typedef int (*OEMSUPPS_PF_CHECK_TOKEN)(int ntokens, const char *tokens[],SuppsBuffer *);
typedef struct token_input
{
  const char *reg_exp;                /* Quasi-regular expression. */
  OEMSUPPS_PF_CHECK_TOKEN check_fn;      /* Function to be called. */
} OEMSUPPS_TOKEN_INPUT;


/************************************************************************
                  Internal Functions
************************************************************************/
static int OEMSUPPS_ChkUSSD(int num_tokens, const char *tokens[], SuppsBuffer *pBuf);
static int OEMSUPPS_ChkChangePin(int num_tokens, const char *tokens[], SuppsBuffer *pBuf);
static int OEMSUPPS_ChkUnblockPin(int num_tokens, const char *tokens[], SuppsBuffer *pBuf);
static int OEMSUPPS_ChkIMEI(int num_tokens, const char *tokens[], SuppsBuffer *pBuf);
static int OEMSUPPS_ChkSS(int num_tokens, const char *tokens[], SuppsBuffer *pBuf);
static int OEMSUPPS_RegexTokenize (const char *in_str, OEMSUPPS_TOKEN_INPUT *inputs, const char *tokens[], void *pBuf);

#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)

static int OEMSUPPS_ChangePin(AEETSuppsMessage *pMsg);
static int OEMSUPPS_UnblockPin(AEETSuppsMessage *pMsg);
static int OEMSUPPS_IMEI(AEETSuppsMessage *pMsg);
static int OEMSUPPS_RegisterSS( AEETSuppsMessage *pMsg);
static int OEMSUPPS_EraseSS (AEETSuppsMessage *pMsg);
static int OEMSUPPS_ActivateSS (AEETSuppsMessage *pMsg);
static int OEMSUPPS_DeactivateSS (AEETSuppsMessage *pMsg);
static int OEMSUPPS_InterrogateSS (AEETSuppsMessage *pMsg);
static int OEMSUPPS_RegPwd (AEETSuppsMessage *pMsg);
static int OEMSUPPS_USSReq (AEETSuppsMessage *pMsg);
static int OEMSUPPS_PwdRes (AEETSuppsResponse *ss_resp);
static int OEMSUPPS_USSNotifyRes (AEETSuppsResponse *ss_resp);
static int OEMSUPPS_USSRes (AEETSuppsResponse *ss_resp);
static int OEMSUPPS_ConvertBSGToNW( AEETSuppsMessage *pMsg);
static int OEMSUPPS_SendSS(AEETSuppsMessage *pMsg);
static int OEMSUPPS_ConvertBSGToLocal( int basic_service);  
static uint32 OEMSUPPS_BCDToNumber(const byte *pBcdNumber,uint32  bcdLength,char *pAddress);

#endif 

#if defined(AEE_SIMULATOR)
static int OEMSUPPS_SendSS(AEETSuppsMessage *pMsg);
#endif


/* The tokens we handle. */
OEMSUPPS_TOKEN_INPUT OEMSUPPS_regex_input[] = {
  {"(\\d\\d)",OEMSUPPS_ChkUSSD},
  {"(\\d)",OEMSUPPS_ChkUSSD},
  { "\\*\\*04(2*)\\*{(\\d+)\\*(\\d+)\\*(\\d+)}#", OEMSUPPS_ChkChangePin },
  { "\\*\\*05(2*)\\*{(\\d+)\\*(\\d+)\\*(\\d+)}#", OEMSUPPS_ChkUnblockPin },
  { "\\*#06#", OEMSUPPS_ChkIMEI },
  {"([*#]+)(\\d+){\\*([\\+\\d]*)\\*(\\d+)\\*(\\d+)\\*(\\d+)}#",OEMSUPPS_ChkSS},
  { NULL, NULL }
};

/* Maximum number of tokens; this value corresponds to the maximum possible tokens
** by any of the strings above. */
#define OEMSUPPS_MAX_TOKENS 6

#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)
/* List of functions that can Start an SS operation 
 * Note that the order of these functions is dependant upon the defines
 * above. 
 */
int (*OEMSUPPSPhoneSSOpFN[])() =
{
  OEMSUPPS_ChangePin,            /* AEETSUPPS_REQ_CHANGE_PIN  */
  OEMSUPPS_UnblockPin,           /* AEETSUPPS_REQ_UNBLOCK_PIN */
  OEMSUPPS_IMEI,                 /* AEETSUPPS_REQ_DEVICE_IMEI  */
  OEMSUPPS_RegisterSS,           /* AEETSUPPS_REQ_REGISTER*/
  OEMSUPPS_EraseSS,              /* AEETSUPPS_REQ_ERASE*/
  OEMSUPPS_ActivateSS,           /* AEETSUPPS_REQ_ACTIVATE*/
  OEMSUPPS_DeactivateSS,         /* AEETSUPPS_REQ_DEACTIVATE*/
  OEMSUPPS_InterrogateSS,        /* AEETSUPPS_REQ_INTERROGATE*/
  OEMSUPPS_RegPwd,               /* AEETSUPPS_REQ_REGISTER_PASSWD*/
  OEMSUPPS_USSReq                /* AEETSUPPS_IND_USS*/
};

/*Functions used to respond to the SS requests made by the newtork*/
int (*OEMSUPPSRespFN[])() =
{
  OEMSUPPS_PwdRes,               /* AEETSUPPS_IND_ENTER_PASSWD*/
  OEMSUPPS_USSNotifyRes,         /* AEETSUPPS_IND_USS_NOTIFY */
  OEMSUPPS_USSRes                /* AEETSUPPS_IND_USS  */
};

/*Total number of SS operations*/
#define OEMSUPPVC_NUM_OPS (sizeof(OEMSUPPSPhoneSSOpFN)/sizeof(OEMSUPPSPhoneSSOpFN[0]))
#endif

/************************************************************************
 ** I N T E R F A C E   F U N C T I O N   D E C L A R A T I O N S
 ************************************************************************/


/* Interface to the SuppService object. */
static uint32 OEMSUPPS_AddRef     (ISuppsTrans *pMe);
static uint32 OEMSUPPS_Release    (ISuppsTrans *pMe);

static AEETSuppsTransState    OEMSUPPS_GetState   (ISuppsTrans * pme);

static void   OEMSUPPS_Run        (ISuppsTrans *pme, AEECallback *pcbWait);


/***********************************************************************
 * D A T A    O B J E C T S
 ***********************************************************************/
static struct ISuppsTrans          *ISuppsTransObj = NULL;

/*===========================================================================
FUNCTION OEMSUPPS_AddRef

DESCRIPTION
  This function is called to add an additional reference to the SuppSvc
  object.

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  None
===========================================================================*/
static uint32 OEMSUPPS_AddRef(ISuppsTrans *pMe)
{
  if (pMe) {
    return (++pMe->m_uRefs);
  }
  return 0;
}

/*===========================================================================
FUNCTION OEMSUPPS_Release

DESCRIPTION
  This function is called when a reference is removed.  It decrements
  the count and if the count reaches 0, it frees the memory.

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  None
===========================================================================*/
static uint32 OEMSUPPS_Release(ISuppsTrans *pMe)
{
   if (!pMe) {
      return (0);
   }

   if (--pMe->m_uRefs != 0) {
      return pMe->m_uRefs;
   }

   // Ref count is zero.  Release memory
   FREE(pMe);
   ISuppsTransObj = NULL;
   return (0);
}

/*===========================================================================
FUNCTION OEMSupps_ParseString

DESCRIPTION
  

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  tokens global is updated.
===========================================================================*/
int OEMSupps_ParseString(const char *pszString, AEETSuppsMessage *pMsg, uint32 *pdwSize)
{
  int  nErr = SUCCESS;
  int  nLen;
  SuppsBuffer theBuf;
  const char *OEMSUPPS_tokens[OEMSUPPS_MAX_TOKENS];

  /* There is no string to parse or nothing to respond to */
  if( NULL == pszString || NULL == pdwSize || 0 == (nLen = STRLEN(pszString)) || NULL == pMsg ) {
     return EBADPARM;
  }

  /* Message buffer must be atleast sizeof(AEETSuppsMessage) */
  if( *pdwSize < sizeof(AEETSuppsMessage) ) {
     *pdwSize = sizeof(AEETSuppsMessage);
     return EBUFFERTOOSMALL;
  }

  /* String is larger than the known maximum */
  if( nLen > AEET_MAX_DIGITS_LENGTH ) {
     return EINVALIDFORMAT;
  }

  theBuf.pMsg = pMsg;
  theBuf.dwExtra = (*pdwSize - sizeof(AEETSuppsMessage));   /* Extra space in the buffer */
  theBuf.dwNeeded = 0;                                      /* To start with we donot need any more space */

  /*Tokenize the String*/
  nErr = OEMSUPPS_RegexTokenize(pszString, OEMSUPPS_regex_input, OEMSUPPS_tokens, &theBuf);

  *pdwSize += theBuf.dwNeeded;                           /* Add the needed size to the presented size */

  return nErr;
}

static ModelListener *g_pListeners;
static AEETSuppsMessage  *g_pMsg;

static void OEMSupps_CancelListener( ModelListener *pl )
{
   ModelListener *pBegin = (ModelListener *)pl->pCancelData;
 
   if( pBegin == pl ) {
      pBegin = pl->pNext;
   }
   else {
      pl->pPrev->pNext = pl->pNext;
   }

   if( pl->pNext ) {
      pl->pNext->pPrev = pl->pPrev;
   }

   pl->pfnCancel     = 0;
   pl->pCancelData   = 0;
}

static void OEMSupps_AddListener( ModelListener *pl )
{
   if( 0 == pl ) {
      return;
   }

   LISTENER_Cancel( pl );

   pl->pfnCancel     = OEMSupps_CancelListener;
   pl->pCancelData   = g_pListeners;
   pl->pPrev         = 0;
   pl->pNext         = g_pListeners;
   g_pListeners      = pl;

   if( pl->pNext ) {
      pl->pNext->pPrev = pl;
   }
}

/*===========================================================================
FUNCTION OEMSUPPS_Run

DESCRIPTION
  This function is called to start the SS running.  Based on the info in the 
  AEETSuppsMessage, the Supplementary Service Operation is started
  If it successfully is started, the event is sent out, otherwise
  it returns an error which this function returns.

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
int OEMSupps_SendMessage(AEETSuppsMessage *pMsg, ModelListener *pListener)
{
#if !defined(FEATURE_GSM) && !defined(FEATURE_WCDMA)
   return EUNSUPPORTED;
#endif

   if( g_pMsg ) {
      return EITEMBUSY;
   }

   if( (AEETSuppsMessage *)0 == pMsg ) {
      return EBADPARM;
   }

   if( !OEMTelephone_IsModeGW(OEMTelephone_GetSystemMode(0)) ) {
      return AEET_ERR_OP_NOT_ALLOWED;
   }

   g_pMsg = pMsg;

   if( pListener ) {
      /* Include this in resume list. */
      OEMSupps_AddListener( pListener );
   }

   return OEMSUPPS_SendSS(pMsg);
}

/*--------------------------------------------------------------------------------------------------------------------*/
#define OEM_functions
/*--------------------------------------------------------------------------------------------------------------------*/

/***********************************************************************
                 * INTERNAL      FUNCTIONS*
 ***********************************************************************/
#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)
/*===========================================================================
FUNCTION  OEMSUPPS_GetSSError 

DESCRIPTION
  Converts the CM SS Error into SuppSvc SS Error

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  Add command in UI command buffer
===========================================================================*/
AEETSuppsErrorType OEMSUPPS_GetSSError
(
  const ie_cm_ss_error_s_type *pIError
)
{
  AEETSuppsErrorType      ss_error = AEETSUPPS_ERR_NO_ERR;
  if(pIError->present)
  {
    ss_error = (AEETSuppsErrorType)pIError->error_code | AEETSUPPS_BM(pIError->error_code_tag);
    MSG_HIGH("Received SS Error %d from CM",ss_error,0,0);
  }
  return ss_error;
}/*OEMSUPPS_GetSSError*/

/*===========================================================================
FUNCTION  OEMSUPPS_GetCCCause 

DESCRIPTION
  Converts the CM CC Cause into ICM CC Cause

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  Add command in UI command buffer
===========================================================================*/

AEECMEndCause OEMSUPPS_GetCCCause
(
  const ie_cm_cc_cause_T *pICause
)
{
  if(!pICause->present){
    MSG_HIGH("CC Cause Info with no Info",0,0,0);
    return AEECM_END_UNAVAILABLE;
  }

  MSG_HIGH("CC Cause Value %d",pICause->cause_value,0,0);
  return ((AEECMEndCause)pICause->cause_value | 0x0100);

}

     

/*===========================================================================
FUNCTION  OEMSUPPS_GetSSStatus

DESCRIPTION
  Converts the CM SS Status into SuppSvc SS Status

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  
===========================================================================*/
boolean OEMSUPPS_GetSSStatus
(
  const ie_ss_status_s_type *pIssStatus,
  AEETSuppsOpStatus        *pOssStatus
)
{
  if(pIssStatus->present)
  {
     pOssStatus->ss_active      = pIssStatus->cm_ss_active;
     pOssStatus->ss_operative   = pIssStatus->cm_ss_operative;
     pOssStatus->ss_provisioned = pIssStatus->cm_ss_provisioned;
     pOssStatus->ss_registered  = pIssStatus->cm_ss_registered;
     MSG_HIGH("Received SS Status from CM",0,0,0);
     return TRUE;
  }
  return FALSE;
}/*OEMSUPPS_GetSSStatus*/

/*===========================================================================
FUNCTION  OEMSUPPS_GetCallBarringInfo

DESCRIPTION
  Converts the CM Call Barring Info into SuppSvc Call Barring Info

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
 
===========================================================================*/
boolean OEMSUPPS_GetCallBarringInfo
(
  const ie_call_barring_info_s_type *pICallBarring,
  AEETSuppsCallBarringInfo         *pOCallBarring
)
{
  uint32 i;
   if(!pICallBarring->present)
     return FALSE;

  MSG_HIGH("Received Call Barring Info from CM",0,0,0);

  /*Supplementary Service Code*/
  if(pICallBarring->cm_ss_code.present)
    pOCallBarring->ss_code = (AEETSuppsCodeType)pICallBarring->cm_ss_code.ss_code;

  /*Info Length*/
  pOCallBarring->length = MIN(pICallBarring->call_barring_info_length,
                              AEETSUPPS_CALL_BARRING_LIST_SIZE);


  for(i=0;i<pOCallBarring->length;i++)
  {
    /*Get the Basic Service Type*/
    if(pICallBarring->call_barring_feature_list[i].basic_service.present)
    {
      pOCallBarring->call_barring_feature_list[i].basic_service =
         (AEETSuppsBasicServiceType)(AEETSUPPS_BM(pICallBarring->call_barring_feature_list[i].basic_service.code_type) |
                                      pICallBarring->call_barring_feature_list[i].basic_service.bs_code);

    pOCallBarring->call_barring_feature_list[i].basic_service=
      (AEETSuppsBasicServiceType)OEMSUPPS_ConvertBSGToLocal(pOCallBarring->call_barring_feature_list[i].basic_service);
    }
    // Get the SS status as well
    (void)OEMSUPPS_GetSSStatus(&pICallBarring->call_barring_feature_list[i].cm_ss_status,
                             &pOCallBarring->call_barring_feature_list[i].ss_status);
  }
  return TRUE;
}/*OEMSUPPS_GetCallBarringInfo*/


/*===========================================================================
FUNCTION  OEMSUPPS_GetFwdInfo

DESCRIPTION
  Converts the Fwd Info into SuppSvc Fwd  Info

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  
===========================================================================*/
boolean OEMSUPPS_GetFwdInfo
(
   const ie_forwarding_info_s_type        *pIfwdInfo,
   AEETSuppsForwardingInfo                *pOfwdInfo
)
{
  uint32 i;
  (void)MEMSET(pOfwdInfo, 0, sizeof(AEETSuppsForwardingInfo));

  if (!pIfwdInfo->present)
  {
    return FALSE;
  }

  MSG_HIGH("Received Fwd Info from CM",0,0,0);
  if(pIfwdInfo->cm_ss_code.present)
    pOfwdInfo->ss_code = (AEETSuppsCodeType) pIfwdInfo->cm_ss_code.ss_code;
  
  pOfwdInfo->feature_list.length=
                MIN(pIfwdInfo->forwarding_feature_list.forwarding_feature_list_length,AEETSUPPS_FWD_FEATURE_LIST_SIZE);

  /*Get the Info for all*/
  for(i=0;i<pOfwdInfo->feature_list.length;i++)
  {
  /*Basic Service*/
    if(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].basic_service.present)
    {
      pOfwdInfo->feature_list.fwd_feature[i].basic_service
       =(AEETSuppsBasicServiceType)(AEETSUPPS_BM(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].basic_service.code_type) |
                                     pIfwdInfo->forwarding_feature_list.forwarding_feature[i].basic_service.bs_code);

    /*Convert to Local Values*/
    pOfwdInfo->feature_list.fwd_feature[i].basic_service=
        (AEETSuppsBasicServiceType)OEMSUPPS_ConvertBSGToLocal(pOfwdInfo->feature_list.fwd_feature[i].basic_service);
    }

  /*Get the SS Status*/
    (void)OEMSUPPS_GetSSStatus(&pIfwdInfo->forwarding_feature_list.forwarding_feature[i].ss_status,
                             &pOfwdInfo->feature_list.fwd_feature[i].ss_status);


  /*Get the forward to Number*/
    pOfwdInfo->feature_list.fwd_feature[i].fwd_to_number.length =0;

    if(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_number[0].present)
    {
      pOfwdInfo->feature_list.fwd_feature[i].fwd_to_number.data = 
             (char*)MALLOC(OEMSUPPS_MAX_FWD_TO_NUMBER);

      pOfwdInfo->feature_list.fwd_feature[i].fwd_to_number.length
            =OEMSUPPS_BCDToNumber((byte*)pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_number[0].data,
                                    pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_number[0].length,
                                    (char*)pOfwdInfo->feature_list.fwd_feature[i].fwd_to_number.data);
    }

    pOfwdInfo->feature_list.fwd_feature[i].long_fwd_to_number.length =0;

    if(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_number[1].present)
    {
      pOfwdInfo->feature_list.fwd_feature[i].long_fwd_to_number.data = 
             (char*)MALLOC(OEMSUPPS_MAX_FWD_TO_NUMBER);

      pOfwdInfo->feature_list.fwd_feature[i].long_fwd_to_number.length=
         OEMSUPPS_BCDToNumber(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_number[1].data,
                                pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_number[1].length,
                                pOfwdInfo->feature_list.fwd_feature[i].long_fwd_to_number.data);

    }

    pOfwdInfo->feature_list.fwd_feature[i].fwd_to_subaddress.length = 0;

    if(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_subaddress.present)
    {
      pOfwdInfo->feature_list.fwd_feature[i].fwd_to_subaddress.data = 
             (char*)MALLOC(OEMSUPPS_MAX_FWD_TO_NUMBER);

      pOfwdInfo->feature_list.fwd_feature[i].fwd_to_subaddress.length = 
          OEMSUPPS_BCDToNumber(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_subaddress.data,
                                 pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarded_to_subaddress.length,
                                 pOfwdInfo->feature_list.fwd_feature[i].fwd_to_subaddress.data);
    }

  /*Get the forwarding options*/
    pOfwdInfo->feature_list.fwd_feature[i].fwd_option.fwd_reason  = AEETSUPPS_FWD_REASON_FWD_REASON_NONE;

    if(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarding_options.present)
    {
       pOfwdInfo->feature_list.fwd_feature[i].fwd_option.fwd_reason 
          =(AEETSuppsFwdReasonType)pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarding_options.forwarding_reason;
       pOfwdInfo->feature_list.fwd_feature[i].fwd_option.notification_to_cp
          = pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarding_options.notification_to_cp;
       pOfwdInfo->feature_list.fwd_feature[i].fwd_option.notification_to_fp
          = pIfwdInfo->forwarding_feature_list.forwarding_feature[i].forwarding_options.notification_to_fp;
    }

  /*Get the timer value*/
    if(pIfwdInfo->forwarding_feature_list.forwarding_feature[i].no_reply_condition_timer.present)
    {
      pOfwdInfo->feature_list.fwd_feature[i].timer_value =
          pIfwdInfo->forwarding_feature_list.forwarding_feature[i].no_reply_condition_timer.timer_value;
    }

  }
 return TRUE;
}/*OEMSUPPS_GetFwdInfo*/

/*===========================================================================
FUNCTION  OEMSUPPS_GetFwdFeatureListInfo

DESCRIPTION
  Converts the Fwd Info into SuppSvc Fwd  Info

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  
===========================================================================*/
boolean OEMSUPPS_GetFwdFeatureListInfo
(  
   const ie_forwarding_feature_list_s_type *pIfwdInfo,
   AEETSuppsFwdFeatureList                *pOfwdInfo
)
{ 
  uint32 i;
  (void)MEMSET(pOfwdInfo, 0, sizeof(AEETSuppsFwdFeatureList));

  if (!pIfwdInfo->present)
  {
    return FALSE;
  }

  MSG_HIGH("Received Fwd Feature List Info from CM",0,0,0);
  
  pOfwdInfo->length=
                MIN(pIfwdInfo->forwarding_feature_list_length,AEETSUPPS_FWD_FEATURE_LIST_SIZE);

  /*Get the Info for all*/
  for(i=0;i<pOfwdInfo->length;i++)
  {
  /*Basic Service*/
    if(pIfwdInfo->forwarding_feature[i].basic_service.present)
    {
      pOfwdInfo->fwd_feature[i].basic_service
       =(AEETSuppsBasicServiceType)(AEETSUPPS_BM(pIfwdInfo->forwarding_feature[i].basic_service.code_type) |
                                     pIfwdInfo->forwarding_feature[i].basic_service.bs_code);

    /*Convert to Local Values*/
    pOfwdInfo->fwd_feature[i].basic_service=
      (AEETSuppsBasicServiceType)OEMSUPPS_ConvertBSGToLocal(pOfwdInfo->fwd_feature[i].basic_service);
    }

  /*Get the SS Status*/
    (void)OEMSUPPS_GetSSStatus(&pIfwdInfo->forwarding_feature[i].ss_status,
                             &pOfwdInfo->fwd_feature[i].ss_status);


  /*Get the forward to Number*/
    pOfwdInfo->fwd_feature[i].fwd_to_number.length = 0;

    if(pIfwdInfo->forwarding_feature[i].forwarded_to_number[0].present)
    {
      pOfwdInfo->fwd_feature[i].fwd_to_number.data
               = (char*)MALLOC(OEMSUPPS_MAX_FWD_TO_NUMBER);

      pOfwdInfo->fwd_feature[i].fwd_to_number.length = 
        OEMSUPPS_BCDToNumber(pIfwdInfo->forwarding_feature[i].forwarded_to_number[0].data,
                               pIfwdInfo->forwarding_feature[i].forwarded_to_number[0].length,
                             pOfwdInfo->fwd_feature[i].fwd_to_number.data);
    }

    pOfwdInfo->fwd_feature[i].long_fwd_to_number.length = 0;

    if(pIfwdInfo->forwarding_feature[i].forwarded_to_number[1].present)
    {
      pOfwdInfo->fwd_feature[i].long_fwd_to_number.data
               = (char*)MALLOC(OEMSUPPS_MAX_FWD_TO_NUMBER);

      pOfwdInfo->fwd_feature[i].long_fwd_to_number.length = 
        OEMSUPPS_BCDToNumber(pIfwdInfo->forwarding_feature[i].forwarded_to_number[1].data,
                               pIfwdInfo->forwarding_feature[i].forwarded_to_number[1].length,
                               pOfwdInfo->fwd_feature[i].long_fwd_to_number.data);
    }

    pOfwdInfo->fwd_feature[i].fwd_to_subaddress.length = 0;

    if(pIfwdInfo->forwarding_feature[i].forwarded_to_subaddress.present)
    {
      pOfwdInfo->fwd_feature[i].fwd_to_subaddress.data
               = (char*)MALLOC(OEMSUPPS_MAX_FWD_TO_NUMBER);

      pOfwdInfo->fwd_feature[i].fwd_to_subaddress.length = 
        OEMSUPPS_BCDToNumber(pIfwdInfo->forwarding_feature[i].forwarded_to_subaddress.data,
                               pIfwdInfo->forwarding_feature[i].forwarded_to_subaddress.length,
                               pOfwdInfo->fwd_feature[i].fwd_to_subaddress.data);
    }


  /*Get the forwarding options*/
   pOfwdInfo->fwd_feature[i].fwd_option.fwd_reason =AEETSUPPS_FWD_REASON_FWD_REASON_NONE;

   if(pIfwdInfo->forwarding_feature[i].forwarding_options.present){
      pOfwdInfo->fwd_feature[i].fwd_option.fwd_reason = 
           (AEETSuppsFwdReasonType)pIfwdInfo->forwarding_feature[i].forwarding_options.forwarding_reason;

      pOfwdInfo->fwd_feature[i].fwd_option.notification_to_cp =
           pIfwdInfo->forwarding_feature[i].forwarding_options.notification_to_cp;

      pOfwdInfo->fwd_feature[i].fwd_option.notification_to_fp =
           pIfwdInfo->forwarding_feature[i].forwarding_options.notification_to_fp;

   }

  /*Get the timer value*/
    if(pIfwdInfo->forwarding_feature[i].no_reply_condition_timer.present)
    {
      pOfwdInfo->fwd_feature[i].timer_value =
          pIfwdInfo->forwarding_feature[i].no_reply_condition_timer.timer_value;
    }

  }
 return TRUE;
}/*OEMSUPPS_GetFwdFeatureListInfo*/

/*===========================================================================
FUNCTION  OEMSUPPS_GetCliRestrictInfo

DESCRIPTION
  Converts the Cli Restrict Info into SuppSvc Cli Restrict Info

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
 
===========================================================================*/
boolean OEMSUPPS_GetCliRestrictInfo
(
  const cli_restriction_info_T   *pICliRestrict,
  AEETSuppsCliRestrictInfo      *pOCliRestrict
)
{
  if(!pICliRestrict->present)
  {
    return FALSE;
  }

  MSG_HIGH("Received Cli Restrict Info from CM",0,0,0);

  (void)OEMSUPPS_GetSSStatus(&pICliRestrict->cm_ss_status,
                             &pOCliRestrict->ss_status);

  if(pICliRestrict->cm_cli_restriction_option.present)
  {
    pOCliRestrict->cli_restriction_option = (AEETSuppsCliRestrictOptionType)pICliRestrict->cm_cli_restriction_option.option;
  }
  return TRUE;
}/*OEMSUPPS_GetCliRestrictInfo*/


/*===========================================================================
FUNCTION  OEMSUPPS_GetUSSData

DESCRIPTION
  Converts the USS Data Info into SuppSvc USS Data Info

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  None
===========================================================================*/
boolean OEMSUPPS_GetUSSData
(
   const cm_uss_data_e_type   ussDataType,
   const uss_data_s_type     *pIUSSData,
   AEETSuppsData            *pOUSSData
)
{

  MSG_HIGH("Received USS Data from CM",0,0,0);

  /*Check the data coding scheme*/
  if( ( pIUSSData->uss_data_coding_scheme & OEMSUPPS_ALPHABET_MASK ) ==
                   OEMSUPPS_DEFAULT_ALPHABET )
  {
     if ( ussDataType == CM_USS_PHASE2_TYPE )
     {
       uint16 num_bits = pIUSSData->size * 8 ;
       uint16 num_chars = num_bits / 7;
       char *uss_data = (char*)MALLOC(MIN(num_chars +1,AEETSUPPS_MAX_DATA_LEN));
    

       pOUSSData->length = MIN(num_chars,AEETSUPPS_MAX_DATA_LEN);

       /* convert default alphabet to ascii */
       cm_util_def_alphabet_to_ascii(  (byte *)&(pIUSSData->ussData),
                                       (uint8)num_chars,
                                       (byte *)uss_data);

       pOUSSData->data = uss_data;
       //Free the data somewhere?? ;

      }
      else if ( ussDataType == CM_USS_PHASE1_TYPE )
      {
       //lint -esym(737, pOUSSData->length)  

     /*simply Store the data*/
         pOUSSData->data = (char*)MALLOC(MIN(pIUSSData->size+1,AEETSUPPS_MAX_DATA_LEN));
         pOUSSData->length = MIN(pIUSSData->size,AEETSUPPS_MAX_DATA_LEN);
         (void)STRCPY(pOUSSData->data, (char*)pIUSSData->ussData);
      }
  }
  return TRUE;
}/*OEMSUPPS_GetUSSData*/
/*===========================================================================
FUNCTION  OEMSUPPS_GetBSGListInfo

DESCRIPTION
  Gets the Completed Event Data when the Completed event is received

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  
===========================================================================*/
 boolean OEMSUPPS_GetBSGListInfo(
  const basic_service_group_list_s_type *pIBsgList, 
  AEETSuppsBasicServiceGroupListInfo   *pOBsgList)
{
  int i;

  (void)MEMSET(pOBsgList, 0, sizeof(AEETSuppsBasicServiceGroupListInfo));

  if (!pIBsgList->present)
  {
    return FALSE;
  }
  pOBsgList->length = pIBsgList->list_length;

  for(i=0;i<pOBsgList->length;i++)
  {
    if(pIBsgList->list[i].present)
    {
      pOBsgList->bsg_list[i] = OEMSUPPS_ConvertBSGToLocal(pIBsgList->list[i].bs_code \
        | (AEETSUPPS_BM(pIBsgList->list[i].code_type )));
    }
  }
  return TRUE;
} /*OEMSUPPS_GetBSGListInfo*/

/*===========================================================================
FUNCTION  OEMSUPPS_GetCUGInfo

DESCRIPTION
  Gets the Completed Event Data when the Completed event is received

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  
===========================================================================*/
 boolean OEMSUPPS_GetCUGInfo
( 
  const ie_cug_info_s_type *pICUGInfo, 
  AEETSuppsData  *pOCUGInfo
)
{
  int i;
  if(!pICUGInfo->present)
  {
    return FALSE;
  }

  pOCUGInfo->length  = pICUGInfo->cug_feature_list_length;

  for(i=0;i<pICUGInfo->cug_feature_list_length;i++){
    pOCUGInfo->data = (char*)MALLOC(OEMSUPPS_CUG_SIZE);
    (void)STRCPY(pOCUGInfo->data,(char*)pICUGInfo->cug_subscription_list[0].cug_index);
  }


  return TRUE;
}/*OEMSUPPS_GetCUGInfo*/
/*===========================================================================
FUNCTION  OEMSUPPS_GetCompletedData

DESCRIPTION
  Gets the Completed Event Data when the Completed event is received

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  
===========================================================================*/
void OEMSUPPS_GetCompletedData
(
  AEETSuppsStatus *pStatus,
  const cm_sups_info_s_type     *sups_info
)
{
  pStatus->status  = AEETSUPPS_STATUS_COMPLETE;

  pStatus->data.Result.result_type = sups_info->conf_type;
  pStatus->data.Result.success = sups_info->ss_success;
  

  MSG_HIGH("Received Conf: %d from CM",sups_info->conf_type,0,0);

  /*Based on the confirmation type ,convert the CM data into App Data*/
  switch(sups_info->conf_type)
  {
    case FWD_INFO:
      pStatus->data.Result.result_type = AEETSUPPS_FWD_INFO;
      pStatus->data.Result.data.fwd_info.ss_code = (AEETSuppsCodeType)sups_info->ss_code; 
      if(!OEMSUPPS_GetFwdInfo(&sups_info->forwarding_info,
                             &pStatus->data.Result.data.fwd_info)) 
      {
         pStatus->data.Result.result_type = AEETSUPPS_NO_INFO;
      } 
     break;


     case FWD_FEATURE_LIST_INFO:
       pStatus->data.Result.result_type = AEETSUPPS_FWD_FEATURE_LIST_INFO;
      if(!OEMSUPPS_GetFwdFeatureListInfo(&sups_info->fwd_feature_list,
                                           &pStatus->data.Result.data.fwd_feature_list))
      {
         pStatus->data.Result.result_type = AEETSUPPS_NO_INFO;
      }
      break;

    case CALL_BARRING_INFO:
      pStatus->data.Result.result_type = AEETSUPPS_CALL_BARRING_INFO;
      pStatus->data.Result.data.call_barring_info.ss_code = 
               (AEETSuppsCodeType)sups_info->ss_code;

      if( !OEMSUPPS_GetCallBarringInfo(&sups_info->call_barring_info,
                                      &pStatus->data.Result.data.call_barring_info))
      {
         pStatus->data.Result.result_type = AEETSUPPS_NO_INFO;
      }
      break;

    case CLI_RESTRICTION_INFO:
      pStatus->data.Result.result_type = AEETSUPPS_CLI_RESTRICTION_INFO;
      if(!OEMSUPPS_GetCliRestrictInfo(&sups_info->cli_restriction,
                                        &pStatus->data.Result.data.cli_restriction))
      {
          pStatus->data.Result.result_type = AEETSUPPS_NO_INFO;
      }
      break;

    case CUG_INFO:
      pStatus->data.Result.result_type = AEETSUPPS_CUG_INFO;
      (void)OEMSUPPS_GetCUGInfo(&sups_info->cug_info, 
                            &pStatus->data.Result.data.cug_info); 
      break;

    case BSG_LIST_INFO :
       pStatus->data.Result.result_type = AEETSUPPS_BSG_LIST_INFO;
      (void)OEMSUPPS_GetBSGListInfo(&sups_info->bsg_list, 
                                &pStatus->data.Result.data.bsg_list_info); 
      break;

    case USS_DATA_INFO:
      pStatus->data.Result.result_type =AEETSUPPS_USS_DATA_INFO;
      if(!OEMSUPPS_GetUSSData( sups_info->uss_data_type,
                                &sups_info->uss_data,
                                &pStatus->data.Result.data.uss_data_info))
      {
         pStatus->data.Result.result_type = AEETSUPPS_NO_INFO;
      }
      break;

    case USSD_DATA_INFO:
       pStatus->data.Result.result_type = AEETSUPPS_USSD_DATA_INFO;
       if(!OEMSUPPS_GetUSSData( sups_info->uss_data_type,
                                  &sups_info->uss_data,
                                  &pStatus->data.Result.data.ussd_data_info))
        {
            pStatus->data.Result.result_type = AEETSUPPS_NO_INFO;
        }
        break;

      case SS_DATA_INFO:
      pStatus->data.Result.result_type = AEETSUPPS_SS_DATA_INFO;
      break;

    case SS_STATUS_INFO:
        pStatus->data.Result.result_type = AEETSUPPS_SS_STATUS_INFO;
       (void)OEMSUPPS_GetSSStatus(&sups_info->ss_status,
                              &pStatus->data.Result.data.ss_status);
     break;
    
   
    case SS_ERROR_INFO:
       pStatus->data.Result.result_type = AEETSUPPS_SS_ERROR_INFO;
       pStatus->data.Result.data.ss_error
          = OEMSUPPS_GetSSError(&sups_info->ss_error);
      break;

    case UNKNOWN_CONF_INFO:
       pStatus->data.Result.result_type = AEETSUPPS_UNKNOWN_CONF_INFO;
      break;
    
    case CC_CAUSE_INFO:
      pStatus->data.Result.result_type = AEETSUPPS_CC_CAUSE_INFO;
      pStatus->data.Result.data.cc_cause =  (uint32)OEMSUPPS_GetCCCause(&sups_info->cc_cause);

     break;

    default:
      pStatus->data.Result.success = FALSE;
      MSG_HIGH("%d Conf Type Ignored",sups_info->conf_type,0,0);
      break; 
  }
}/*OEMSUPPS_GetCompletedData*/


/*===========================================================================
FUNCTION OEMSUPPS_SendNotification

DESCRIPTION
  This function will send the EVT_NOTIFY to all registered tasks.  It
  is called via the RESUME callback mechanism and guarentees we are in
  Brew space to send the event.

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
void OEMSUPPS_SendNotification(OEMSUPPS_NOTIFIER_NOTIFY_CB *pUser)
{
 // ISHELL_Notify(ISUPPSVC_NOTIFIERobj->m_pIShell, AEECLSID_SUPPSVC_NOTIFIER,
 //       pUser->mask, &pUser->user_data);

}


                      /*Call Back Functions*/

/*===========================================================================
FUNCTION OEMSUPPS_EvtCb

DESCRIPTION


DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
/*CM Sups Event Call back*/
static void OEMSUPPS_EvtCb
(
  void *data
)
{
  static OEMSUPPS_NOTIFIER_NOTIFY_CB pData;
   

  OEMSUPPSEventCB  *supsCb = (OEMSUPPSEventCB*) data;
  cm_sups_info_s_type  *sups_info = (cm_sups_info_s_type*)MALLOC(sizeof(cm_sups_info_s_type));
  cm_sups_event_e_type sups_event = (cm_sups_event_e_type)supsCb->event;

  (void)MEMCPY(sups_info,(cm_sups_info_s_type *)supsCb->data,sizeof(cm_sups_info_s_type));

  /*Free the AEECallBack pointer*/
  --supsCb->nRef;
   
  if (supsCb->cb.pfnCancel) {
    (*(supsCb->cb.pfnCancel))(&supsCb->cb);
    supsCb->cb.pfnCancel = NULL;
  }

  if (supsCb->data)
    FREE(supsCb->data);

  supsCb->data = NULL;

  supsCb->bInUse = FALSE;

   /*Process the CM event.*/
  MSG_HIGH("Received %d ,Sups Event from CM",supsCb->event,0,0);

  MSG_HIGH("The SS Ref is %d, SS Code is %d,",sups_info->ss_ref,sups_info->ss_code,0);

   
  switch(sups_event)
  {
/*--------------------------Started Events------------------------------------*/
/*For all the started events , the state will be switched from OEMSUPPS_ENTER to  
  OEMSUPPS_REQ_SRV. Wait for the CONF event from CM*/
    case CM_SUPS_EVENT_REGISTER:
    case CM_SUPS_EVENT_ACTIVATE:
    case CM_SUPS_EVENT_DEACTIVATE:
    case CM_SUPS_EVENT_ERASE:
    case CM_SUPS_EVENT_INTERROGATE:
    case CM_SUPS_EVENT_REG_PASSWORD:
    case CM_SUPS_EVENT_PROCESS_USS:
      //?? What do we do here?
       break;

/*-------------------------Confirmation Events----------------------------------*/
/*For all the Completed Events, the state is changed to AEETSUPPS_STATE_DONE. Send all 
  the information in the right format to the client*/

    case CM_SUPS_EVENT_REGISTER_CONF:
    case CM_SUPS_EVENT_ACTIVATE_CONF:
    case CM_SUPS_EVENT_DEACTIVATE_CONF:
    case CM_SUPS_EVENT_ERASE_CONF:
    case CM_SUPS_EVENT_INTERROGATE_CONF:
    case CM_SUPS_EVENT_REG_PASSWORD_CONF:
    case CM_SUPS_EVENT_PROCESS_USS_CONF:
      OEMSUPPS_GetCompletedData(&ISuppsTransObj->m_result,sups_info);
      ISuppsTransObj->m_transState = AEETSUPPS_STATE_DONE;
      //Call the Cb
      break;

    

/*---------------------------NW Init Events------------------------------*/
/*Network Initiated Events. A response is required from the client for each 
  of these events*/

    case CM_SUPS_EVENT_FWD_CHECK_IND:
      pData.mask = AEET_NMASK_NEW_NI_SUPP_TRANS;
      /*Invoke Id is generated by the n/w*/
      pData.user_data.transaction_id = sups_info->invoke_id ;
      pData.user_data.ind_type  = AEETSUPPS_IND_FWD_CHECK;
      ISuppsTransObj->m_InvokeId = sups_info->invoke_id;

      ISuppsTransObj->m_result.status = AEETSUPPS_STATUS_IND;
      ISuppsTransObj->m_result.data.NetworkInd.ind_type = AEETSUPPS_IND_FWD_CHECK;
      /*Change the current state to AEETSUPPS_STATE_NW_INDICATION-> App needs to respond to this event*/
      
      ISuppsTransObj->m_transState = AEETSUPPS_STATE_NW_INDICATION;
      OEMSUPPS_SendNotification(&pData);
      break;

    case CM_SUPS_EVENT_USS_NOTIFY_IND:
      pData.mask = AEET_NMASK_NEW_NI_SUPP_TRANS;
      /*Invoke Id is generated by the n/w*/
      pData.user_data.transaction_id = sups_info->invoke_id ;
      pData.user_data.ind_type  = AEETSUPPS_IND_USS_NOTIFY;
      ISuppsTransObj->m_InvokeId = sups_info->invoke_id;

      ISuppsTransObj->m_result.status = AEETSUPPS_STATUS_IND;
      ISuppsTransObj->m_result.data.NetworkInd.ind_type = AEETSUPPS_IND_USS_NOTIFY;
      /*Change the current state to AEETSUPPS_STATE_NW_INDICATION-> App needs to respond to this event*/
      
     
    /*Convert the Sups data to AECHAR*/
     if( ( sups_info->uss_data.uss_data_coding_scheme & OEMSUPPS_ALPHABET_MASK ) ==
                                                      OEMSUPPS_DEFAULT_ALPHABET )
      {
        uint16 num_bits = sups_info->uss_data.size * 8 ;
        uint16 num_chars = num_bits / 7;
        char *uss_data = (char*)MALLOC(MIN(num_chars+1,AEETSUPPS_MAX_DATA_LEN));

        /* convert default alphabet to ascii */
        cm_util_def_alphabet_to_ascii(  (byte *)sups_info->uss_data.ussData,
                                         (uint8)num_chars,
                                         (byte*)uss_data);
 
        ISuppsTransObj->m_result.data.NetworkInd.ind_data.data = uss_data;
        //Free it once the event has been sent.
      }

      ISuppsTransObj->m_transState = AEETSUPPS_STATE_NW_INDICATION;
      
      OEMSUPPS_SendNotification(&pData);
      break;

    case CM_SUPS_EVENT_USS_IND:
      pData.mask = AEET_NMASK_NEW_NI_SUPP_TRANS;
      /*Invoke Id is generated by the n/w*/
      pData.user_data.transaction_id = sups_info->invoke_id ;
      pData.user_data.ind_type  = AEETSUPPS_IND_USS;
      ISuppsTransObj->m_InvokeId = sups_info->invoke_id;

      ISuppsTransObj->m_result.status = AEETSUPPS_STATUS_IND;
      ISuppsTransObj->m_result.data.NetworkInd.ind_type = AEETSUPPS_IND_USS;

      /*Change the current state to AEETSUPPS_STATE_NW_INDICATION-> App needs to respond to this event*/
      ISuppsTransObj->m_transState = AEETSUPPS_STATE_NW_INDICATION;

      if( ( sups_info->uss_data.uss_data_coding_scheme & OEMSUPPS_ALPHABET_MASK ) ==
                                                      OEMSUPPS_DEFAULT_ALPHABET )
      {
        uint16 num_bits = sups_info->uss_data.size * 8 ;
        uint16 num_chars = num_bits / 7;
        char *uss_data = (char*)MALLOC(MIN(num_chars+1,AEETSUPPS_MAX_DATA_LEN));

        /* convert default alphabet to ascii */
        cm_util_def_alphabet_to_ascii(  (byte *)sups_info->uss_data.ussData,
                                         (uint8)num_chars,
                                         (byte*)uss_data);
 
        ISuppsTransObj->m_result.data.NetworkInd.ind_data.data = uss_data;
        //Free it once the event has been sent.    
      }
      OEMSUPPS_SendNotification(&pData);
      break;

    case CM_SUPS_EVENT_GET_PASSWORD_IND:
      pData.mask = AEET_NMASK_NEW_NI_SUPP_TRANS;
      /*Invoke Id is generated by the n/w*/
      pData.user_data.transaction_id = sups_info->invoke_id ;
      ISuppsTransObj->m_InvokeId = sups_info->invoke_id;

      ISuppsTransObj->m_result.status = AEETSUPPS_STATUS_IND;
      
      /*Change the current state to AEETSUPPS_STATE_NW_INDICATION-> App needs to respond to this event*/
      ISuppsTransObj->m_transState = AEETSUPPS_STATE_NW_INDICATION;

    /*Get the Pwd Info*/
       if ( enterPW == sups_info->guidance_info)
       {
         pData.user_data.ind_type         = AEETSUPPS_IND_ENTER_PASSWD;
         ISuppsTransObj->m_result.data.NetworkInd.ind_type = AEETSUPPS_IND_ENTER_PASSWD;
       }
       else if(enterNewPW == sups_info->guidance_info) 
       {
         pData.user_data.ind_type         = AEETSUPPS_IND_ENTER_NEW_PASSWD;
         ISuppsTransObj->m_result.data.NetworkInd.ind_type = AEETSUPPS_IND_ENTER_NEW_PASSWD;
       
       }
       else if(enterNewPW_Again == sups_info->guidance_info)
       {
         pData.user_data.ind_type         = AEETSUPPS_IND_ENTER_NEW_PASSWD_AGAIN;
         ISuppsTransObj->m_result.data.NetworkInd.ind_type = AEETSUPPS_IND_ENTER_NEW_PASSWD_AGAIN;
       }
      OEMSUPPS_SendNotification(&pData);
      break;


/*---------------------------Response to NW events-----------------------*/
/*Response sent from the Client to network initiated events*/
  
    case CM_SUPS_EVENT_USS_NOTIFY_RES:
    case CM_SUPS_EVENT_USS_RES:
    case CM_SUPS_EVENT_GET_PASSWORD_RES:
      ISuppsTransObj->m_result.status  = AEETSUPPS_STATUS_COMPLETE;
      ISuppsTransObj->m_transState = AEETSUPPS_STATE_DONE;
      break;
     
/*---------------------------Release Events------------------------------*/

   case CM_SUPS_EVENT_RELEASE_USS_IND:
   case CM_SUPS_EVENT_RELEASE:
      ISuppsTransObj->m_transState = AEETSUPPS_STATE_DONE;
      // Do What with it?
      break;

   default:
      MSG_ERROR("Event %d not handled", sups_event,0,0);
      break;  
  }

  FREE(sups_info);

  /*Remove entry from table*/
  if(ISuppsTransObj->m_transState == AEETSUPPS_STATE_DONE)
  {
    ISuppsTransObj->m_transState = AEETSUPPS_STATE_NONE;
  }
  
  
  
}

/*=============================================================================
FUNCTION: OEMSUPPS_CMEventCB

DESCRIPTION:  
This function is called in the DMSS Context. It will save all the necessary 
information and switch to BREW context to process each of the CM events. This
CB only deals with the SUPS related events. It is this callback function that 
is registered with CM whenever ISuppsTrans is initialized.

DEPENDENCIES:
  None

SIDE EFFECTS:
  None

=============================================================================*/
static void OEMSUPPS_CMEventCB
(
  cm_sups_event_e_type          sups_event,
  const cm_sups_info_s_type     *sups_info
)
{
  OEMSUPPSEventCB  *supsCb = NULL;
  int i;
  
  
  MSG_HIGH("Received Sups Event 0x%X from DMSS CM", sups_event, 0, 0);

  if (!ISuppsTransObj) {
    MSG_ERROR("Unexpected NULL pointer", 0, 0, 0);
    return;
  }

  /*Get the event call back pointer from ISuppsTrans*/
  OEMSUPPS_MUTEX_LOCK();
  for ( i = 0; i < OEMSUPPS_MAX_CB; ++i) {
    if (!ISuppsTransObj->m_evtcb[i].bInUse) {
      supsCb = &ISuppsTransObj->m_evtcb[i];
      supsCb->bInUse = TRUE;
      break;
    }
  }
  OEMSUPPS_MUTEX_UNLOCK();

  if(i >= OEMSUPPS_MAX_CB)
  {
    MSG_ERROR("No Callbacks Available", 0, 0, 0);
  }
  
  /*Initialize AEECallback pointer */
  (void)MEMSET(&supsCb->cb, 0, sizeof(AEECallback));

  if(supsCb->data)
   FREE(supsCb->data);

  supsCb->data = (cm_sups_info_s_type*)MALLOC(sizeof(cm_sups_info_s_type));
  if (!supsCb->data) {
   MSG_ERROR("Unable to allocate memory for callback data", 0, 0, 0);
   supsCb->bInUse = FALSE;
   return;
  }
  (void)MEMSET(supsCb->data, 0, sizeof(cm_sups_info_s_type));
  supsCb->nRef = 1;
  
  supsCb->event = sups_event;

  (void)MEMCPY(supsCb->data, sups_info, sizeof(cm_sups_info_s_type));

  CALLBACK_Init(&(supsCb->cb), OEMSUPPS_EvtCb, supsCb);

  /*Switch to Brew Context/
#ifdef FEATURE_BREW_3_0
  AEE_ResumeCallback(&(supsCb->cb), 0);
#else
  AEE_ResumeCallback(&(supsCb->cb), AEE_RESUME_CB_SYS);
#endif*/

  return;
}


/*===========================================================================
FUNCTION  OEMSUPPS_ErrCb

DESCRIPTION
  Called when a SUPS command error (from other tasks) happens. This callback is 
  registered with CM during ISuppsTrans init.

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
===========================================================================*/
static void OEMSUPPS_ErrCb
(
  void *data
)
{
  static OEMSUPPS_NOTIFIER_NOTIFY_CB pData;
  OEMSUPPSEventCB  *supsCb = (OEMSUPPSEventCB*) data;
  uint32 i=0;
  int sups_cmd;

  /*Send error event to the client*/
  for(i=0;i<OEMSSUPPS_MAX_CMD;i++)
  {
    if(OEMSUPPSCMCmdConversionTable[i].net_code == supsCb->cmd)
     {
       sups_cmd = OEMSUPPSCMCmdConversionTable[i].local;
       break;
     }
  } 

  if(i >= OEMSSUPPS_MAX_CMD)
  {
    MSG_HIGH("Unknown SS Cmd %d Received", supsCb->cmd, 0, 0);
    return;
  }
  
  //TODO: send the actual error to the app
}

/*=============================================================================
FUNCTION: OEMSUPPS_CMErrorCB

DESCRIPTION:  
This function is called in the DMSS Context. It will save all the necessary 
information and switch to BREW context to process each of the CM events. This
CB only deals with the SUPS Errors. It is this callback function that 
is registered with CM whenever ISuppsTrans is initialized.

DEPENDENCIES:
  None

SIDE EFFECTS:
  None

=============================================================================*/
static void OEMSUPPS_CMErrorCB
(
  cm_client_id_type           client,
  cm_sups_cmd_e_type          cmd,
  cm_sups_cmd_err_e_type      cmd_err
)
{
  //lint -save -esym(715, cmd)

  OEMSUPPSEventCB  *supsCb = NULL;
  int i;
  
  if (cmd_err == CM_SUPS_CMD_ERR_NOERR)
  {
     return;
  }

  
  MSG_HIGH("Received Sups Error 0x%X from DMSS CM", cmd_err, 0, 0);

  if (!ISuppsTransObj) {
    MSG_ERROR("Unexpected NULL pointer", 0, 0, 0);
    return;
  }

  /*Get the event call back pointer from ISuppsTrans*/
  OEMSUPPS_MUTEX_LOCK();
  for ( i = 0; i < OEMSUPPS_MAX_CB; ++i) {
    if (!ISuppsTransObj->m_evtcb[i].bInUse) {
      supsCb = &ISuppsTransObj->m_evtcb[i];
      supsCb->bInUse = TRUE;
      break;
    }
  }
  OEMSUPPS_MUTEX_UNLOCK();

  if(i >= OEMSUPPS_MAX_CB)
  {
    MSG_ERROR("No Callbacks Available", 0, 0, 0);
  }
  
  /*Initialize AEECallback pointer */
  (void)MEMSET(&supsCb->cb, 0, sizeof(AEECallback));

  if(supsCb->data)
    FREE(supsCb->data);

  supsCb->nRef = 1;
  
  supsCb->cmd = cmd;
  supsCb->cmd_err = cmd_err;

  CALLBACK_Init(&(supsCb->cb), OEMSUPPS_ErrCb, supsCb);

  /*Switch to Brew Context/
#ifdef FEATURE_BREW_3_0
  AEE_ResumeCallback(&(supsCb->cb), 0);
#else
  AEE_ResumeCallback(&(supsCb->cb), AEE_RESUME_CB_SYS);
#endif*/

  return;
}


/*===========================================================================
FUNCTION  OEMSUPPS_CmdCb

DESCRIPTION
  Called by Call manager to indicate status of SUPS command

DEPENDENCIES

RETURNS
  None

SIDE EFFECTS
  Add command in UI command buffer
===========================================================================*/
void OEMSUPPS_CmdCb (
  void*                   data_block_ptr,
  cm_sups_cmd_e_type      cmd,
  cm_sups_cmd_err_e_type  cmd_err
)
{
  if (data_block_ptr == NULL)  // we do not use data_block_ptr for now
  {
    MSG_LOW("Data Block Pointer is NULL",0,0,0);
  }

  OEMSUPPS_CMErrorCB(client_sups, cmd, cmd_err);

}
#endif /* FEATURE_WCDMA || F_GSM */

/************************************************************************
 ** I N T E R F A C E   F U N C T I O N   D E F I N I T I O N S
 ************************************************************************/

/*===========================================================================
FUNCTION OEMSUPPS_New

DESCRIPTION
  This function is called to create a new Supplementary Services object.

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  None
===========================================================================*/
int OEMSUPPS_New(IShell *pIShell, void **ppif)
{
#ifdef AEE_SIMULATOR
   // Do not create an object is this is being run on the SDK.
   *ppif = NULL;
   return EUNSUPPORTED;
#endif

   // Check parameters.
   if ((!pIShell) || (!ppif)) {
      return EBADPARM;
   }

   if (ISuppsTransObj == NULL)
   {
     // Allocate the object.
     if ((ISuppsTransObj = (ISuppsTrans *)MALLOC(sizeof(ISuppsTrans))) == NULL) {
        return ENOMEMORY;
     }

     ISuppsTransObj->m_pIShell = pIShell;
     ISuppsTransObj->m_uRefs = 1;
     ISuppsTransObj->m_transId = 0;
  
     *ppif = ISuppsTransObj;

#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)
     /*For now use CM_CLIENT_TYPE_FLOATING4 , change to CM_CLIENT_TYPE_BREW*/
    
      (void)cm_client_init(CM_CLIENT_TYPE_FLOATING4, &client_sups);

      (void)cm_client_sups_reg( client_sups,                       // pointer to the client struct
                          OEMSUPPS_CMEventCB,                 // pointer to a cb function
                          CM_CLIENT_EVENT_REG,
                          CM_SUPS_EVENT_REGISTER,          // from this call event
                          CM_SUPS_EVENT_GET_PASSWORD_RES,  // to this call event
                          OEMSUPPS_CMErrorCB);               // pointer to a cb function for errors

      (void) cm_client_act(client_sups);
#endif /* F_WCDMA || F_GSM */
      
   }
   else
   {
     (void)OEMSUPPS_AddRef(ISuppsTransObj);
     *ppif = ISuppsTransObj;
   }
   return AEE_SUCCESS;
}

/*===========================================================================
FUNCTION OEMSUPPS_RegExCharsMatch 

DESCRIPTION
  This function is called to compare two characters against eachother,
  but handles the special characters associated with the near-regular
  expressions.

DEPENDENCIES

SIDE EFFECTS
===========================================================================*/
static boolean OEMSUPPS_RegExCharsMatch(boolean special_char, char match_char, char src)
{
  if (special_char)     /* Do we treat this special */
  {
    switch (match_char)
    {
      case 'd': /* Currently, we only handle digits as special characters */
        return (src >= '0' && src <= '9');
      default:
        MSG_MED("Unknown special character %d\n", match_char, 0, 0);
        return FALSE;
    }
  }
  else
  {
    /* Normal characters are just compared. */
    return (src == match_char);
  }
}
/* <EJECT> */
/*===========================================================================
FUNCTION OEMSUPPS_RegexToMatch

DESCRIPTION
  This function is called to compare a token (group of characters)
  to the current portion of the regular expression.  This function
  will handle the cases when there are choices of characters or multiple
  characters as part of the token.  Upon completion, it moves the input
  pointers past the token in the input and regular expression strings.

  The formating understood includes:

  [] to indicate a choice of multiple characters that my match.
  \d indicates digit.
  * indicates 0 or more.
  + indicates 1 or more.

DEPENDENCIES

SIDE EFFECTS
===========================================================================*/
static boolean OEMSUPPS_RegexToMatch( const char **src_ptr, const char **regex_ptr)
{
  boolean special_char = FALSE;  /* Are we processing a special character */
  boolean multi_char = FALSE;    /* Does this token have multiple characters */
  boolean choice_exists = FALSE; /* Is there a choice of characters */
  int min_num_chars_to_match;   /* Number of characters necessary (0 or 1) */
  char match_char;              /* The character we are trying to match. */
  const char *start_of_regex = *regex_ptr;  /* Save the start of the current regex */
  const char *end_reg_ptr;            /* Save the end of the current regex. */
  const char *tmp_reg_ptr;            /* Work variable. */
  int num_chars_matched = 0;    /* How long is the matching string. */

  end_reg_ptr = start_of_regex+1; /* End initially is the start + 1 */
  switch (*start_of_regex)
  {
    case '[':                   /* We are going to have a choice. */
      choice_exists = TRUE;
      start_of_regex++;         /* The characters to match start next */

      /* Find the end of the regular expression */
      while ((*end_reg_ptr != ']') && (*end_reg_ptr != '\0'))
      {
        end_reg_ptr++;
      }

      if (*end_reg_ptr != ']')
      {
        MSG_ERROR("Error in regular expression; no closing ]", 0, 0, 0);
        return FALSE;
      }

      end_reg_ptr++;    /* End points to either the start of the next or the
                           repeat character */
      break;
    case '\\':          /* Escaped character? */
      end_reg_ptr++;    /* The regular expression takes an extra character. */
      break;
    default:
      break;
  }

  /* Now we check the character afterwards to see if it specifies a count. */
  switch (*(end_reg_ptr))
  {
    case '*':   /* Specifies 0 or more */
      multi_char = TRUE;
      min_num_chars_to_match = 0;
      end_reg_ptr++;
      break;
    case '+':   /* Specifies 1 or more */
      multi_char = TRUE;
      min_num_chars_to_match = 1;
      end_reg_ptr++;
      break;
    default:    /* No repeat counts */
      multi_char = FALSE;
      min_num_chars_to_match = 1;
  }

  tmp_reg_ptr = start_of_regex;         /* Initialize work variable */
  do {
    match_char = *tmp_reg_ptr;          /* We are searching for this char */

    // Check for escaped characters.
    if (match_char == '\\')             /* Unless it is escaped. */
    {
      match_char = *++tmp_reg_ptr;      /* Get the char after the backslash */
      switch (match_char)
      {
        case 'd':                       /* D is the only special char we know */
          special_char = TRUE;
          break;
        default:
          special_char = FALSE;
          break;
      }
    }

    /* Now check to see if the match_char from the regular expression matches
     * the current character in the input string. */
    if (OEMSUPPS_RegExCharsMatch(special_char, match_char,
          *((*src_ptr) + num_chars_matched)))
    {
      /* We have a match, mark that we did. */
      num_chars_matched++;
      tmp_reg_ptr = start_of_regex;
    }
    else
    {
      /* It doesn't match.  Either we are done matching to this regular
       * expression or we have more choices. */
      if (choice_exists)
      {
        tmp_reg_ptr++;
        if (*tmp_reg_ptr == ']') /* No more choices, we are done. */
          break;
      }
      else
        break;
    }
  } while (multi_char || choice_exists);

  /* Now to see if we are actually matching what was specified. */
  if (num_chars_matched >= min_num_chars_to_match)
  {
    /* Yep, move things beyond this regular expression */
    *src_ptr += num_chars_matched;
    *regex_ptr = end_reg_ptr;
    return TRUE;
  }
  else
  {
    /* Nope.  */
    return FALSE;
  }
}

/*===========================================================================
FUNCTION OEMSUPPS_RegexTokenize

DESCRIPTION
  This function is called to compare a series of regular expressions
  to a single input_string.  If the strings match, we call the function
  associated with the regular expression.  This function should process
  the string and return the command to be executed.  The caller can then
  call the appropriate function to handle the request.

  The regular expression formating understood by this function is:
    () to indicate save this part in one of the tokens.
    NOTE: the tokens are not NULL terminated by this function.
    The input string is preserved unless the called function modifies them.

DEPENDENCIES

SIDE EFFECTS
===========================================================================*/
static int OEMSUPPS_RegexTokenize (const char *in_str, OEMSUPPS_TOKEN_INPUT *inputs, const char *tokens[], void *pMsg)
{
  int ntokens;          /* Number of tokens we have saved. */
  const char *current_in;     /* Current place in the input string. */
  const char *tmp_ptr;        /* Work variable when we may need to save it. */
  const char *current_regex;  /* Current place of the regular expression */
  OEMSUPPS_TOKEN_INPUT *curr_ptr = inputs; /* Current regular express */
  boolean found_match = FALSE; /* Used to loop across multiple reg_exps */
  boolean optional_match = FALSE; /* Marks this part of the regex as optional */
  boolean do_save = FALSE; /* Should we save this if it matches. */

  /* While we need to search and haven't found it. */
  while ((found_match == FALSE) && (curr_ptr->reg_exp != NULL))
  {
    /* New expression, init our variables. */
    current_in = in_str;                /* Start at beginning of source */
    current_regex = curr_ptr->reg_exp;  /* Start at beginning of regexp */
    found_match = TRUE;                 /* Assume we will match. */
    ntokens = 0;                        /* We haven't saved anything yet. */
    optional_match = FALSE;
    do_save = FALSE;

    /* While we are looking good. */
    while ((found_match) && (*current_regex != '\0'))
    {
      switch (*current_regex) /* Check if we handle the regular expression */
      {
        case '{':               /* this portion of the string is optional */
          optional_match = TRUE;
          current_regex++;
          break;
        case '}':               /* end the string is optional */
          optional_match = FALSE;
          current_regex++;
          break;
        case '(':               /* Save the current token. */
          do_save = TRUE;
          current_regex++;
          break;
        case ')':               /* Really a no-op since its up to the
                                   parsing function to mark the end. */
          current_regex++;
          break;
        default:
          /* We don't handle the character, so see if the token matches */
          tmp_ptr = current_in;
          found_match = OEMSUPPS_RegexToMatch(&current_in, &current_regex);
          if (found_match)
          {
            if (do_save)
            {
              tokens[ntokens++] = tmp_ptr;
            }
          }
          else if (optional_match)
          {
            // If we didn't find a match, it may mean we are in an
            // optional part of the expression.  Skip to the end of
            // the optional part now and resume comparing there.
            while ((*current_regex++ != '}') && (*current_regex != '\0'))
            {
              if (*current_regex == '\\') current_regex++;
              current_regex++;
            }
            found_match = TRUE;
          }
          do_save = FALSE;
          break;
      }
    }

    /* Done checking regular expression... if everything matches... */
    if (found_match && (*current_in == '\0'))
    {
      /* Everything matched, call the function associated with it. */
      return ((*(curr_ptr->check_fn))(ntokens, tokens, pMsg));
    }

    /* We don't have a match, check next regular expression. */
    found_match = FALSE;
    curr_ptr++;
  }

  /* Return an indication that we did not find a match. */
  return AEET_ERR_SUPPS_STRING_NO_MATCH;
}

#if defined(AEE_SIMULATOR)
static int OEMSUPPS_SendSS(AEETSuppsMessage *pMsg)
{
   return EUNSUPPORTED;
}
#endif
 
#if defined(FEATURE_WCDMA) || defined(FEATURE_GSM)
/*===========================================================================
FUNCTION OEMSUPPS_SendSS

DESCRIPTION
  Send the SS structure and the appropriate command to the lower layers.
DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
 None
===========================================================================*/
static int OEMSUPPS_SendSS(AEETSuppsMessage *pMsg)
{

  int returnVal = EFAILED;

  /*Send the request to CM*/
  if(pMsg->data.request.operation <= AEETSUPPS_REQ_NETWORK_IND){
     returnVal = ((*OEMSUPPSPhoneSSOpFN [pMsg->data.request.operation])(pMsg));
  }
  else
  {
    MSG_ERROR("Bad SS Operation %d",pMsg->data.request.operation,0,0);
    return EFAILED;
  }

  if(returnVal == SUCCESS) {
    returnVal = SUCCESS;
    ISuppsTransObj->m_transId = 0; // Temporary value
    MSG_HIGH("SS Started - SS Code %d, SS Ref -%d",pMsg->data.request.code,ISuppsTransObj->m_transId,0);
  }
  
  return returnVal;
}

/*===========================================================================
FUNCTION OEMSUPPS_ConvertBSGToNW

DESCRIPTION
  Converts the basic service from a local value to a network value
DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
 None
===========================================================================*/
static int OEMSUPPS_ConvertBSGToNW( AEETSuppsMessage *pMsg)
{
   int n, nErr;

   /*Exception - Register Passwd does not have a basic service*/
   if(pMsg->data.request.operation == AEETSUPPS_REQ_REGISTER_PASSWD) {
      return SUCCESS;
   }

   nErr = EFAILED;

   for( n = 0; n < OEMSSUPPS_MAX_BSG_ENTRY; n++ ) {
      if( OEMSUPPSBSGConversionTable[n].local == pMsg->data.request.basic_service) {
         pMsg->data.request.code  = OEMSUPPSBSGConversionTable[n].net_code;
         nErr = SUCCESS;
         break;
      }
   }

   return nErr;
}

/*===========================================================================
FUNCTION OEMSUPPS_ConvertBSGToLocal

DESCRIPTION
  Converts the basic service from a local value to a network value
DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
 None
===========================================================================*/
static int OEMSUPPS_ConvertBSGToLocal( int basic_service )
{
   int n = 0;

   for( n = 0; n < OEMSSUPPS_MAX_BSG_ENTRY; n++ ) {

      if( OEMSUPPSBSGConversionTable[n].net_code == basic_service) {
         
         return(OEMSUPPSBSGConversionTable[n].local);
      }
   }
   
   return n;
}

/*===========================================================================
FUNCTION ISuppsTrans_NumberToBCD

DESCRIPTION
  This function is called to convert the number into a BCD format

DEPENDENCIES
  None.

RETURN VALUE
  Length of the BCD Number

SIDE EFFECTS
  Converts the number into a BCD format
===========================================================================*/
static int OEMSUPPS_NumberToBCD
(
  ISuppsTrans *po,
  const byte *src,
  uint32 len,
  byte *dest
)
{

  cm_num_s_type number;
  uint8 bcd_len;
  

  MSG_LOW("OEMSUPPS_NumberToBCD Called len %d",len,0,0);

  if(src == NULL || dest == NULL)
  {
    MSG_ERROR("Bad Pointer",0,0,0);
    return 0;
  }


  /*Default Values*/
  number.len           = 0;
  number.pi            = 0;
  number.si            = 0;
  number.digit_mode    = CM_DIGIT_MODE_8BIT_ASCII;

  if (src[0] == '+' )
  {
    number.number_type = CM_NPI_ISDN;

    (void)MEMCPY( number.buf, (src + 1), len -1);
    number.len = len - 1 ;
  }
  else {
    (void)MEMCPY( number.buf, (src ), len );
    number.len = len  ;
  }

  /*Convert number to BCD*/
  cm_util_number_to_bcd( (const cm_num_s_type*)&number, dest);

  bcd_len  = 2;                         // (LENGTH + TON+NPI)
  bcd_len += ((1 + number.len)/2);      // Rest of the digits.

  MSG_HIGH("Returned length %d", bcd_len, 0, 0);
  return bcd_len;
}

/*===========================================================================
FUNCTION OEMSUPPS_BCDToNumber

DESCRIPTION
  This function is called to convert the BCD Number number into an ascii format

DEPENDENCIES
  None.

RETURN VALUE
  Length of the Ascii Number

SIDE EFFECTS
  Converts the BCD number into ascii format
===========================================================================*/
static uint32 OEMSUPPS_BCDToNumber
(
  const byte *pBcdNumber,
  uint32  bcdLength,
  char *pAddress
)
{
  byte *asciiNumber = (byte*)MALLOC(CM_CALLED_PARTY_BCD_NO_LENGTH);
  byte *pBuffer = (byte*)MALLOC(CM_CALLED_PARTY_BCD_NO_LENGTH);
  uint32 len =0;

  MSG_LOW("OEMSUPPS_BCDToNumber Called",0,0,0);

  /*Check for invalid values*/
  if(pBcdNumber == NULL || pAddress == NULL || asciiNumber == NULL || pBuffer == NULL)
  {
    MSG_ERROR("Bad Pointer",0,0,0);
    FREEIF(asciiNumber);
    FREEIF(pBuffer);
    return 0;
  }

  (void)MEMSET (pBuffer, 0xFF, sizeof(pBuffer));
  pBuffer[0] = bcdLength;
  (void)MEMCPY( &pBuffer[1],
           pBcdNumber,
           bcdLength);

  /*Convert to ASCII values*/
  cm_util_bcd_to_ascii((byte *)pBuffer, asciiNumber );

  /*Save string to ouput param*/
  if( asciiNumber[0] != '\0' )
  {
    len = (byte)STRLEN((char *)asciiNumber);
    (void)STRCPY( pAddress, (char*)asciiNumber);
  }

  FREE(asciiNumber);
  FREE(pBuffer);
  return len;
}
#endif 

size_t strnchrcpy( char *pszDest, const char *pszSrc, const char *pszTerm, size_t nSize )
{
   size_t nRet;

   if( !nSize ) {
      return nSize;
   }

   nRet = nSize;

   while( nSize > 1 && *pszSrc && !STRCHR( pszTerm, *pszSrc ) ) {
      *pszDest++ = *pszSrc++;
      nSize--;
   }

   *pszDest = '\0';        /* NULL terminate */
   nRet -= nSize;

   return nRet;
}

/*===========================================================================
FUNCTION OEMSUPPS_ChkChangePin

DESCRIPTION
  This function is called to determine if the parameters entered are good
  for changing the PIN.

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_ChkChangePin(int num_tokens, const char *tokens[], SuppsBuffer *pBuf)
{
#ifdef FEATURE_MMGSDI
   AEETSuppsMessage* pMsg;
   AEETSuppsChangePassword *pPass;
   int    nLen;

   /* The expression specifying this string has multiple formats. */
   /* However, only the complete format executes the command. */

   if( num_tokens != 4 ) {
      return AEET_ERR_SUPPS_STRING_NO_MATCH;
   }

   /* **04[2]*<old_pin>*<new_pin>*<new_pin># legal. */
   /* Token0     1          2         3*/

   pMsg = pBuf->pMsg;
   pPass = &pMsg->data.request.req.passwd;

   /* Copy the old PIN. */
   nLen = strnchrcpy( pPass->szCurPasswd, tokens[1], "*", AEETSUPPS_MAX_PASSWD_LEN );
   /* Verify old  PIN */
   if( !INRANGE( nLen, 4, GSDI_PIN_LEN ) ) {
      return AEET_ERR_SUPPS_STRING_BAD_PARAM;
   }

   nLen = strnchrcpy( pPass->szNewPasswd, tokens[2], "*", AEETSUPPS_MAX_PASSWD_LEN );
   /* Verify new PIN */
   if( !INRANGE( nLen, 4, GSDI_PIN_LEN ) ) {
      return AEET_ERR_SUPPS_STRING_BAD_PARAM;
   }

   nLen = strnchrcpy( pPass->szNewPasswdRepeated, tokens[3], "#", AEETSUPPS_MAX_PASSWD_LEN );
   /* Verify new PIN */
   if( !INRANGE( nLen, 4, GSDI_PIN_LEN ) ) {
      return AEET_ERR_SUPPS_STRING_BAD_PARAM;
   }

   pMsg->type = AEETSUPPS_MSG_REQUEST;
   pMsg->data.request.operation = AEETSUPPS_REQ_CHANGE_PIN;

   return SUCCESS;
#else
   return EUNSUPPORTED;
#endif
}

#if defined(FEATURE_GSM) || defined(FEATURE_WCDMA)
/*===========================================================================
FUNCTION OEMSUPPS_PinCmdCb

DESCRIPTION
  The callback Function for GSDI

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
void OEMSUPPS_PinCmdCb(gsdi_cnf_T *retval)
{
  static AEETSuppsStatus pStatus;
  AEETSuppsPinStatus pinStatus;
  
  switch (retval->change_pin_cnf.message_header.gsdi_status)
  {
    case GSDI_SUCCESS:
     pinStatus = AEETSUPPS_PIN_SUCCESS;
     break;
    case GSDI_INCOMPAT_PIN_STATUS:
     pinStatus =  AEETSUPPS_PIN_ERR_INCOMPATIBLE;
     break;
    case GSDI_CODE_BLOCKED:
      pinStatus = AEETSUPPS_PIN_ERR_BLOCKED;
      break;
    case GSDI_INCORRECT_CODE:
      pinStatus = AEETSUPPS_PIN_ERR_INCORRECT;
      break;
    default:
     pinStatus = AEETSUPPS_PIN_ERR_UNKNOWN;
  }

  pStatus.status = AEETSUPPS_STATUS_COMPLETE;
  pStatus.data.Result.result_type = AEETSUPPS_PIN_INFO;
  pStatus.data.Result.data.pin_status = pinStatus; 

  //ResumeAppCb
  
}

/*===========================================================================
FUNCTION OEMSUPPS_ChangePin

DESCRIPTION
  This function is called when the parameters entered are good and
  we need to attempt to change the PIN.


DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_ChangePin(AEETSuppsMessage *pMsg)
{
#ifdef FEATURE_MMGSDI
  gsdi_card_apps_T card_apps;

#ifdef FEATURE_MMGSDI_DUAL_SLOT
  gsdi_slot_id_type slot_id = GSDI_SLOT_NONE;
  boolean slot2_active = FALSE;
#else
  byte num_retry_left;  /* Variable so GSDI can say whats left. */
#endif

  boolean slot1_active = FALSE;


  /* Clear out the user input. */
  if (MEMCMP(pMsg->data.request.req.passwd.szNewPasswd, pMsg->data.request.req.passwd.szNewPasswdRepeated, (OEMSUPPS_MAX_PIN_LEN)))
  {
    // Resume Cb with AEETSUPPS_PIN_ERR_INCOMPATIBLE
    return EFAILED;
  }
  else
  {
    gsdi_returns_T gsdi_retval;

    gsdi_get_apps_available(&card_apps);

    if(card_apps.slot1_present && (
       card_apps.apps_enabled & GSDI_GSM_SIM_MASK ||
       card_apps.apps_enabled & GSDI_USIM_APP_MASK))
    {
      slot1_active = TRUE;
      MSG_MED("Slot 1 is active",0,0,0);
    }

#ifdef FEATURE_MMGSDI_DUAL_SLOT
    if(card_apps.slot2_present &&
       (card_apps.apps2_enabled & GSDI_GSM_SIM_MASK ||
        card_apps.apps2_enabled & GSDI_USIM_APP_MASK)
      )
    {
      slot2_active  = TRUE;
      MSG_MED("Slot 2 is active",0,0,0);
    }

    if(slot1_active && 
       (card_apps.operational_slot & GSDI_GSM_SLOT_1_MASK ||
        card_apps.operational_slot & GSDI_USIM_SLOT_1_MASK )
      )
    {
      slot_id = GSDI_SLOT_1;
    }
    else if(slot2_active && 
            (card_apps.operational_slot & GSDI_GSM_SLOT_2_MASK ||
             card_apps.operational_slot & GSDI_USIM_SLOT_2_MASK)
           )
   {
     slot_id = GSDI_SLOT_2;
   }

  MSG_MED("Slot Id #%d is operational",slot_id,0,0);

  slot_id == GSDI_SLOT_NONE ? (gsdi_retval = GSDI_ERROR):
                              (gsdi_retval = gsdi2_change_pin (slot_id,
                                                              ISuppsTransObj->m_pin,
                                                              (char *)pMsg->data.request.req.passwd.szCurPasswd,
                                                              (char *)pMsg->data.request.req.passwd.szNewPasswd,
                                                              NULL,
                                                              0,
                                                              OEMSUPPS_PinCmdCb 
                                                             ));
#else
   slot1_active ?
   ( gsdi_retval = gsdi_change_pin(ISuppsTransObj->m_pin, 
                                  (char *) pMsg->data.request.req.passwd.szCurPasswd,
                                  (char *) pMsg->data.request.req.passwd.szNewPasswd, 
                                  (byte *) &num_retry_left, 
                                  0, 
                                  OEMSUPPS_PinCmdCb)
                                  ):(gsdi_retval = GSDI_ERROR);
#endif /*FEATURE_MMGSDI_DUAL_SLOT*/

    
    //ResumeCb

    /* Now take the results and display the appropriate message. */
    switch (gsdi_retval)
    {
      case GSDI_SUCCESS:
        return SUCCESS;
      default:
        MSG_ERROR("GSDI ERROR",0,0,0); 
        return EFAILED;
    }
  }
#else
  return EUNSUPPORTED;
#endif
}
#endif

/*===========================================================================
FUNCTION OEMSUPPS_ChkUnblockPin

DESCRIPTION
  This function is called to determine if the parameters entered are good
  for unblocking the PIN.

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_ChkUnblockPin(int num_tokens, const char *tokens[], SuppsBuffer *pBuf)
{
#ifdef FEATURE_MMGSDI
   AEETSuppsMessage *pMsg;
   AEETSuppsChangePassword *pPass;
   int    nLen;

   /* The expression specifying this string has multiple formats. */
   /* However, only the complete format executes the command. */

   if( num_tokens != 4 ) {
      return AEET_ERR_SUPPS_STRING_NO_MATCH;
   }

   /* **04[2]*<old_pin>*<new_pin>*<new_pin># legal. */
   /* Token0     1          2         3*/

   pMsg = pBuf->pMsg;
   pPass = &pMsg->data.request.req.passwd;

   /* Copy the old PIN. */
   nLen = strnchrcpy( pPass->szCurPasswd, tokens[1], "*", AEETSUPPS_MAX_PASSWD_LEN );
   /* Verify old  PIN */
   if( !INRANGE( nLen, 4, GSDI_PIN_LEN ) ) {
      return AEET_ERR_SUPPS_STRING_BAD_PARAM;
   }

   nLen = strnchrcpy( pPass->szNewPasswd, tokens[2], "*", AEETSUPPS_MAX_PASSWD_LEN );
   /* Verify new PIN */
   if( !INRANGE( nLen, 4, GSDI_PIN_LEN ) ) {
      return AEET_ERR_SUPPS_STRING_BAD_PARAM;
   }

   nLen = strnchrcpy( pPass->szNewPasswdRepeated, tokens[3], "#", AEETSUPPS_MAX_PASSWD_LEN );
   /* Verify new PIN */
   if( !INRANGE( nLen, 4, GSDI_PIN_LEN ) ) {
      return AEET_ERR_SUPPS_STRING_BAD_PARAM;
   }

   pMsg->type = AEETSUPPS_MSG_REQUEST;
   pMsg->data.request.operation = AEETSUPPS_REQ_UNBLOCK_PIN; 

   return SUCCESS;
#else
   return EUNSUPPORTED;
#endif
}

#if defined(FEATURE_GSM) || defined(FEATURE_WCDMA)
/*===========================================================================
FUNCTION OEMSUPPS_UnblockPin

DESCRIPTION
  This function is called when the parameters entered are good and
  we need to attempt to unblock the PIN.

  The input parameters are as follows:
  tokens[0] = PIN_ID
  tokens[1] = puk
  tokens[2] = new_pin
  tokens[3] = verify_new_pin

DEPENDENCIES
  None.

RETURN VALUE
  None

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_UnblockPin(AEETSuppsMessage *pMsg)
{
#ifdef FEATURE_MMGSDI
  gsdi_card_apps_T card_apps;

#ifdef FEATURE_MMGSDI_DUAL_SLOT
  gsdi_slot_id_type slot_id = GSDI_SLOT_NONE;
  boolean slot2_active = FALSE;
#else
   byte num_retry_left;  /* Variable so GSDI can say whats left. */
#endif
  boolean slot1_active = FALSE;

  if (MEMCMP(pMsg->data.request.req.passwd.szNewPasswd, pMsg->data.request.req.passwd.szNewPasswdRepeated, AEETSUPPS_MAX_PASSWD_LEN))
  {
    return AEETSUPPS_PIN_ERR_INCOMPATIBLE;
  }
  else
  {
    gsdi_returns_T gsdi_retval;
      
    gsdi_get_apps_available(&card_apps);

    if(card_apps.slot1_present && (
       card_apps.apps_enabled & GSDI_GSM_SIM_MASK ||
       card_apps.apps_enabled & GSDI_USIM_APP_MASK))
    {
      slot1_active = TRUE;
      MSG_MED("Slot 1 is active",0,0,0);
    }

#ifdef FEATURE_MMGSDI_DUAL_SLOT
    if(card_apps.slot2_present &&
       (card_apps.apps2_enabled & GSDI_GSM_SIM_MASK ||
       card_apps.apps2_enabled & GSDI_USIM_APP_MASK)
    )
    {
      slot2_active  = TRUE;
      MSG_MED("Slot 2 is active",0,0,0);
    }

    if(slot1_active && 
       (card_apps.operational_slot & GSDI_GSM_SLOT_1_MASK ||
        card_apps.operational_slot & GSDI_USIM_SLOT_1_MASK )
      )
    {
      slot_id = GSDI_SLOT_1;
    }
    else if(slot2_active && 
            (card_apps.operational_slot & GSDI_GSM_SLOT_2_MASK ||
             card_apps.operational_slot & GSDI_USIM_SLOT_2_MASK)
           )
   {
     slot_id = GSDI_SLOT_2;
   }

  MSG_MED("Slot Id #%d is operational",slot_id,0,0);

  slot_id == GSDI_SLOT_NONE ? (gsdi_retval = GSDI_ERROR):
                              (gsdi_retval = gsdi2_unblock_pin(slot_id,
                                                              ISuppsTransObj->m_pin,
                                                              pMsg->data.request.req.passwd.szCurPasswd,
                                                              (char*)pMsg->data.request.req.passwd.szNewPasswd,
                                                              NULL,
                                                              0,
                                                              OEMSUPPS_PinCmdCb 
                                                             ));
#else
   slot1_active ?
   (gsdi_retval = gsdi_unblock_pin(ISuppsTransObj->m_pin,
                                   pMsg->data.request.req.passwd.szCurPasswd,
                                   (char *) pMsg->data.request.req.passwd.szNewPasswd, 
                                   (byte *) &num_retry_left,
                                   0, 
                                   OEMSUPPS_PinCmdCb)):
   (gsdi_retval = GSDI_ERROR);
#endif /*FEATURE_MMGSDI_DUAL_SLOT*/


   //ResumeCb

    /* Now analyze the return code to see how it went. */
    switch (gsdi_retval)
    {
      case GSDI_SUCCESS:
        return SUCCESS;
      default:
        MSG_ERROR("GSDI_ERROR",0,0,0);
        return EFAILED;
    }
  }
#else
  return EUNSUPPORTED;
#endif
}
#endif

/*===========================================================================
FUNCTION OEMSUPPS_ChkIMEI

DESCRIPTION
  This function is called to verify the parameters of the IMEI display.
  Since there are no parameters, this function simply returns the command
  number for IMEI.

DEPENDENCIES
  None.

RETURN VALUE
  Command number.

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_ChkIMEI(int num_tokens, const char *tokens[], SuppsBuffer *pBuf)
{

   if( num_tokens != 0 ) {
      return AEET_ERR_SUPPS_STRING_NO_MATCH;
   }

   pBuf->pMsg->type = AEETSUPPS_MSG_REQUEST;
   pBuf->pMsg->data.request.operation = AEETSUPPS_DEVICE_IMEI;
   return SUCCESS;
}

#if defined(FEATURE_GSM) || defined(FEATURE_WCDMA)
/*===========================================================================
FUNCTION OEMSUPPS_GetIMEI

DESCRIPTION
  This function fills in the imei into the given byte array.  The
  input string must be at least AEETSUPPS_MAX_IMEI_LEN.

DEPENDENCIES

SIDE EFFECTS
===========================================================================*/
int OEMSUPPS_GetIMEI(byte imei_ascii[])
{
  byte imei_bcd_len = 0;
  int bcd_index = 0;
  int ascii_index = 0;
  byte asc_1 = 0;
  byte asc_2 = 0;

  byte oemnv_imei[(AEETSUPPS_MAX_IMEI_LEN+2)];
  byte imei[AEETSUPPS_MAX_IMEI_LEN+2];
  int result = SUCCESS;

  /* This is a valid IMEI */
  (void)MEMSET(imei, 0, (AEETSUPPS_MAX_IMEI_LEN+2));

  /* <todo> Get the device item IMEI </todo> 
  result = ICONFIG_GetItem(ISuppsTrans_Config, CFGI_IMEI, oemnv_imei,AEETSUPPS_MAX_IMEI_LEN+2);
  */

  /*
  ** CONVERT IT INTO ASCII
  */

  /* The first byte of NV ue_imei is the length of IMEI BCDs */
  imei_bcd_len = oemnv_imei[0];

  if (imei_bcd_len == 0 || result != SUCCESS)
  {
    (void)MEMCPY((byte *) imei_ascii, (byte *) " NOT SET", 8);
    return STRLEN(" NOT SET");
  }

  if( imei_bcd_len < AEETSUPPS_MAX_IMEI_LEN+2 )
  {
    /*
    ** THIS IS A VALID IMEI, SO CONVERT IT TO ASCII
    */
    for( bcd_index = 1; bcd_index <= (int) imei_bcd_len; bcd_index++ )
    {
      asc_1 = (oemnv_imei[bcd_index] & 0x0F);
      asc_2 = (oemnv_imei[bcd_index] & 0xF0) >> 4;
      imei[ascii_index++] = (asc_1 <= 9)?asc_1+'0'
                                              :asc_1-10+'A';
      imei[ascii_index++] = (asc_2 <= 9)?asc_2+'0'
                                              :asc_2-10+'A';
    }

   (void)MEMCPY( imei_ascii, imei + 1, (ascii_index - 2) );

    return (ascii_index - 2);
  } //  if( imei_bcd_len < NV_UE_IME...
  else
  {
    return 0;
  }
}

/*===========================================================================
FUNCTION OEMSUPPS_IMEI

DESCRIPTION
  This function is called to get the IMEI to be displayed.

DEPENDENCIES
  None.

RETURN VALUE
  Command number.

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_IMEI(AEETSuppsMessage *pMsg)
{
  byte imei[AEETSUPPS_MAX_IMEI_LEN+2];
  int len;

  ISuppsTransObj->m_result.status = AEETSUPPS_STATUS_COMPLETE;
  ISuppsTransObj->m_result.data.Result.result_type = AEETSUPPS_DEVICE_IMEI;
     
  MSG_LOW("OEMSUPPS_IMEI Called",0,0,0);

  if ((len = OEMSUPPS_GetIMEI(imei)) > 0)
  {
     STRCPY(ISuppsTransObj->m_result.data.Result.data.imei,(char*)imei);
     // resumeCB  
     return SUCCESS;
  }
  else
    // resumeCB  
    return EFAILED;

}
#endif

boolean OEMSUPPS_IsDigit(char c)
{
  return (c >= '0' && c <= '9');
}



/*===========================================================================
FUNCTION OEMSUPPS_ChkSS

DESCRIPTION

DEPENDENCIES
  None.

RETURN VALUE
  Command number.

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_ChkSS(int num_tokens, const char *tokens[], SuppsBuffer *pBuf)
{
#if defined (FEATURE_WCDMA) || defined (FEATURE_GSM)
   char szWorkBuf[AEET_MAX_DIGITS_LENGTH];
   int i;
   const char *ss_str;
   OEMSUPPS_OPERATION         *current_ss_operation = OEMSUPPS_operation_input;
   uint8 str_len;
   boolean ss_match = FALSE;
   int ss_operation;
   char bsg[OEMSUPPS_MAX_SIA_LEN + 1];
   char sia[OEMSUPPS_MAX_SIA_LEN + 1];
   char sib[OEMSUPPS_MAX_SIB_LEN + 1];
   char sic[OEMSUPPS_MAX_SIC_LEN + 1];
   char ss_code[OEMSUPPS_MAX_SC_LEN + 1];
   AEETSuppsMessage*    sups_start = (AEETSuppsMessage*) pBuf->pMsg;

   if(num_tokens <= 0) {
      return AEET_ERR_SUPPS_STRING_NO_MATCH;
   }

   if( 0 == STRNCMP(tokens[0], "*31#", 4) || 0 == STRNCMP(tokens[0], "#31#", 4) ) {
      return AEET_ERR_SUPPS_STRING_BAD_PARAM;
   }

   ss_str = tokens[0];
   str_len = (uint8)STRLEN(ss_str);

   for (i =0;!OEMSUPPS_IsDigit(ss_str[i]);i++) {
      szWorkBuf[i] = ss_str[i];
   }

   /* STEP 1: Find the SS operation */
   while(current_ss_operation->sups_operation != NULL) {
      if( 0 == STRCMP( szWorkBuf, current_ss_operation->sups_operation) ) {
         ss_operation = current_ss_operation->op_code;
         break;
      }
      current_ss_operation++;
   }

   if( num_tokens > 1 ) {
      strnchrcpy( szWorkBuf, tokens[1], "#*", AEET_MAX_DIGITS_LENGTH );
   }
   else {
      return AEET_ERR_SUPPS_STRING_NO_MATCH;
   }

   if( 0 == STRCMP( szWorkBuf, OEMSUPPS_LOCAL_BSG_REG_PASSWD ) ) {
      ss_operation = AEETSUPPS_REQ_REGISTER_PASSWD;
   }
   else if( NULL == current_ss_operation->sups_operation ) {
      return AEET_ERR_SUPPS_STRING_NO_MATCH;
   }

   sups_start->type = AEETSUPPS_MSG_REQUEST;
   sups_start->data.request.operation = ss_operation;

   if ( ss_operation <= AEETSUPPS_REQ_REGISTER_PASSWD ) {
      /* By now the operation must have been identified */
      /* STEP 2: Find the SI fields */
      if( num_tokens > 1 ) {
         strnchrcpy( ss_code, tokens[1], "#*", sizeof(ss_code) );
      }
      else {
         ss_code[0] = '\0';
      }

      if( num_tokens > 2 ) {
         strnchrcpy( sia, tokens[2], "#*", sizeof(sia) );
      }
      else {
         sia[0] = '\0';
      }

      if( num_tokens > 3 ) {
         strnchrcpy( sib, tokens[3], "#*", sizeof(sib) );
      }
      else {
         sib[0] = '\0';
      }

      if( num_tokens > 4 ) {
         strnchrcpy( sic, tokens[4], "#*", sizeof(sic) );
      }
      else {
         sic[0] = '\0';
      }

      /* by now SIA, SIB, SIC fields must have been separated out */
      /* STEP 3: Convert SC to network SC and update the
                sups_user_data field */
      ss_match = FALSE;
      for( i = 0; i < OEMSUPPS_MAX_ENTRY; i++ ){
         if( 0 == STRNCMP( OEMSUPPSSCConversionTable[i].local_sc, ss_code, OEMSUPPS_MAX_SC_LEN ) ) {
            sups_start->data.request.code = OEMSUPPSSCConversionTable[i].net_sc;
            ss_match = TRUE;
            break;
         }
      }

      /* by now the translation of SC must be complete */
      /* STEP 4: Check for BSG . This may be in SIA, SIB or SIC */
      if (ss_match) {
         if( (sups_start->data.request.operation != AEETSUPPS_REQ_REGISTER_PASSWD)
             && (AEETSUPPS_IS_ALL_CF(sups_start->data.request.code) || AEETSUPPS_IS_RSTRCT(sups_start->data.request.code)) ) {
            /* BSG is in SIB */
            (void)STRCPY( bsg, sib );
         }
         else if( sups_start->data.request.code == AEETSUPPS_CODE_CW ) {
            /* BSG is in  SIA */
            (void)STRCPY( bsg, sia );
         }
         else {
            bsg[0] = '\0';
         }

         /* by now BSG must be identified */
         /* STEP 5: Convert BSG to net BSG */
         sups_start->data.request.basic_service = AEETSUPPS_BASIC_SERVICE_ALL;

         /* special case */
         if ( sups_start->data.request.operation != AEETSUPPS_REQ_REGISTER_PASSWD) {
            /*  BSG - Basic Service Group :
                     BS  = Bearer Service
                     TS  = Tele Service
            */
            ss_match = FALSE;
            for( i = 0; i < OEMSSUPPS_MAX_STR_BSG_ENTRY; i++ ) {
               if( 0 == STRNCMP( OEMSUPPSStrBSGConversionTable[i].local_bsg, bsg, OEMSUPPS_MAX_BSG_LEN ) ) {
                  sups_start->data.request.basic_service  = OEMSUPPSStrBSGConversionTable[i].net_bsg_code;
                  ss_match = TRUE;
                  break;
               }
            }
         }
      }

      /* STEP 6:  Convert DN, if any */
      if ( ss_match) {
         if( ( sups_start->data.request.code & 0xF0 ) == AEETSUPPS_CODE_ALL_FORWARDING_SS ) {
            if(sups_start->data.request.operation == AEETSUPPS_REQ_REGISTER && sia[0] == '\0') {
               return AEET_ERR_SUPPS_STRING_BAD_PARAM;
            }

            if( 0 != (sups_start->data.request.req.reg.data.length = STRLEN(sia)) ) {

               if( sups_start->data.request.req.reg.data.length > pBuf->dwExtra ) {
                  pBuf->dwNeeded = sups_start->data.request.req.reg.data.length - pBuf->dwExtra;
                  return EBUFFERTOOSMALL;
               }

               sups_start->data.request.req.reg.data.data = (char *)(sups_start+1);
               (void)STRCPY(sups_start->data.request.req.reg.data.data, sia);
            }
         }
      }

      /* STEP 7: Check is activation is also registration? */
      if( sups_start->data.request.operation == AEETSUPPS_REQ_ACTIVATE ) {
         if( sups_start->data.request.req.reg.data.length > 0 )
            sups_start->data.request.operation = AEETSUPPS_REQ_REGISTER;
         else if( sups_start->data.request.req.reg.nr_timer != 0 )
            sups_start->data.request.operation = AEETSUPPS_REQ_REGISTER;
      }

      /* STEP 8: Set the NR timer */
      if( (sups_start->data.request.operation == AEETSUPPS_REQ_REGISTER ) && AEETSUPPS_IS_CF(sups_start->data.request.code)) {

         if( sic[0] != '\0' )
            sups_start->data.request.req.reg.nr_timer = (uint8)ATOI(sic);
         else
            sups_start->data.request.req.reg.nr_timer = 0;
      }

      /* STEP 9: copy the password */
      if ( ss_match) {
         if( AEETSUPPS_IS_ALL_CF(sups_start->data.request.code) 
             && sups_start->data.request.operation != AEETSUPPS_REQ_REGISTER_PASSWD) {
            (void)STRCPY(sups_start->data.request.req.passwd.szCurPasswd, sia);
         }
      }

      /* copy old_pwd, new_pwd, new_pwd_again */
      if( sups_start->data.request.operation == AEETSUPPS_REQ_REGISTER_PASSWD) {
         if((sia[0] == '\0' || sib[0] == '\0' || sic[0] == '\0' )) {
            ss_match = FALSE;
         }
         else {
            /*OLD Passwd*/
            (void)STRCPY((char*)sups_start->data.request.req.passwd.szCurPasswd, (char*)sia);

            /*New Passwd*/
            (void)STRCPY((char*)sups_start->data.request.req.passwd.szNewPasswd, (char*)sib);

            /*New Passwd Again*/
            (void)STRCPY((char*)sups_start->data.request.req.passwd.szNewPasswdRepeated,(char*)sic );
         }
      }
   }

   if ( !ss_match ) { /* check if it is an Unstructured SS data */
      if( ( str_len <= AEETSUPPS_MAX_DATA_LEN ) && ( ss_str[str_len - 1] == '#' ) ) {

         sups_start->data.request.operation = AEETSUPPS_REQ_USS;
         ss_match = TRUE;
         if( str_len > pBuf->dwExtra ) {
            pBuf->dwNeeded = str_len - pBuf->dwExtra;
            return EBUFFERTOOSMALL;
         }
         sups_start->data.request.req.ussd.data = (char *)(sups_start+1);
         (void)STRCPY(sups_start->data.request.req.ussd.data ,ss_str);
         sups_start->data.request.req.ussd.length = str_len;
      }
   }

   if(ss_match && ss_str[str_len - 1] == '#') {
      MSG_LOW("Valid SS String",0,0,0);
      return SUCCESS;
   }
#endif /* FEATURE_WCDMA || FEATURE_GSM */

   return AEET_ERR_SUPPS_STRING_NO_MATCH;
}

/*===========================================================================
FUNCTION OEMSUPPS_ChkUSSD

DESCRIPTION

DEPENDENCIES
  None.

RETURN VALUE
  Command number.

SIDE EFFECTS
  Plays with the display
===========================================================================*/
static int OEMSUPPS_ChkUSSD(int num_tokens, const char *tokens[], SuppsBuffer *pBuf)
{
   uint8 str_len;
   boolean bValid = FALSE;
   const char *ss_str;
   AEETSuppsMessage *pMsg = pBuf->pMsg;

   if(num_tokens == 0){
      return AEET_ERR_SUPPS_STRING_NO_MATCH;
   }

   str_len = (uint8)STRLEN(tokens[0]);
   ss_str  = tokens[0];

   /* ALL 1 digit and 2 digit numbers [EXCEPT CALLINDEPENDENT SUPS]are USSD if there is a call up
   ** If not in a call then all 2 digit numbers not starting  with 1 are USSDs*/

   if( str_len > 0  && str_len <= 2 ) {
      if( /* <todo> check if there is a voice call </todo> 
          AEECM_IS_VOICECALL_PRESENT(ISuppsTrans_CM) || */
          ( str_len == 2 && ss_str[0] != '1' ) ){
         bValid = TRUE;
      }
   }

   /*Fill the structure if required*/ 
   if( bValid ) {

      pMsg->type = AEETSUPPS_MSG_REQUEST;
      pMsg->data.request.operation = AEETSUPPS_REQ_USS;

      if( str_len > pBuf->dwExtra ) {
         pBuf->dwNeeded = str_len - pBuf->dwExtra;
         return EBUFFERTOOSMALL;
      }
      pBuf->dwNeeded = 0;

      pMsg->data.request.req.ussd.data = (char *)(pMsg+1);
      (void)STRCPY(pMsg->data.request.req.ussd.data, tokens[0]);
      pMsg->data.request.req.ussd.length = str_len;

      return SUCCESS;
   }

   return AEET_ERR_SUPPS_STRING_NO_MATCH;
}


#if defined(FEATURE_GSM) || defined(FEATURE_WCDMA)
/*===========================================================================
FUNCTION OEMSUPPS_RegisterSS

DESCRIPTION
    Send a RegisterSS request

DEPENDENCIES
    ISUPSSVC and CM interface must be initialized

SIDE EFFECTS
  None
===========================================================================*/
static int OEMSUPPS_RegisterSS( AEETSuppsMessage *pMsg)
{
  cm_reg_ss_params_s_type       *reg_cmd_parms = (cm_reg_ss_params_s_type*)MALLOC(sizeof(cm_reg_ss_params_s_type));

  MSG_HIGH("OEMSUPPS_RegisterSS Called",0,0,0);

  if(reg_cmd_parms == NULL)
  {
    MSG_ERROR("No Resources in ISuppsTransSVC",0,0,0);
    return EFAILED;
  }

  /* set all the fields of the register SS request */

  /* ss_ref */
  reg_cmd_parms->ss_ref   = (uint8)ISuppsTransObj->m_transId;

  /* service code */
  reg_cmd_parms->ss_code  = (uint8)pMsg->data.request.code;

  /* basic service group information */
  reg_cmd_parms->basic_service.bs_code = pMsg->data.request.basic_service & 0xff;
  reg_cmd_parms->basic_service.code_type = pMsg->data.request.basic_service >> 16; /*BS_CODE or TS_CODE*/
  reg_cmd_parms->basic_service.present = \
    (reg_cmd_parms->basic_service.code_type == NO_CODE )? FALSE:TRUE;

  /* forwarded to number*/
  if(pMsg->data.request.req.reg.data.length != 0)
  {
    char *address = (char*)MALLOC(pMsg->data.request.req.reg.data.length + 1);

    (void)STRCPY(address, pMsg->data.request.req.reg.data.data);

    (void)OEMSUPPS_NumberToBCD(ISuppsTransObj, (byte*)address, pMsg->data.request.req.reg.data.length, (byte*)address);

    reg_cmd_parms->fwd_to_num.length = address[0];
    (void)MEMCPY (reg_cmd_parms->fwd_to_num.data,
            &address[1],
            address[0]);

    reg_cmd_parms->fwd_to_num.present = TRUE;
    FREE(address);
  }
  else
    reg_cmd_parms->fwd_to_num.present = FALSE;

  /* forwarded to subaddress */
  reg_cmd_parms->fwd_to_subaddr.present = FALSE;

  /* no reply condition timer */
  if(pMsg->data.request.req.reg.nr_timer != 0 )
  {
    reg_cmd_parms->nr_timer.present     = TRUE;
    reg_cmd_parms->nr_timer.timer_value = (uint8)pMsg->data.request.req.reg.nr_timer;
  }
  else
    reg_cmd_parms->nr_timer.present = FALSE;

  /* send the command to the CM command queue */
  if (cm_sups_cmd_register( OEMSUPPS_CmdCb, NULL, client_sups, reg_cmd_parms) == FALSE)
  {
    /*Either reg_cmd_params is NULL or no more resources in cm*/
    FREE(reg_cmd_parms);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }

  FREE(reg_cmd_parms);
  return SUCCESS;
}
/*===========================================================================

FUNCTION OEMSUPPSSVC_ERASESS

DESCRIPTION
  Send an EraseSS request

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_EraseSS (AEETSuppsMessage *pMsg)
{
  cm_erase_ss_params_s_type    *erase_cmd_parms = (cm_erase_ss_params_s_type*)MALLOC(sizeof(cm_erase_ss_params_s_type));

  MSG_HIGH("OEMSUPPS_EraseSS Called",0,0,0);

  if(erase_cmd_parms == NULL)
  {
    MSG_ERROR("No Resources in ISuppsTransSVC",0,0,0);
    return EFAILED;
  }

  /* set all the fields of the Erase SS request */

  erase_cmd_parms->ss_ref = (uint8)ISuppsTransObj->m_transId;

  /* Service code */
  erase_cmd_parms->ss_code = (uint8)pMsg->data.request.code;

  /* basic service group information */
  erase_cmd_parms->basic_service.bs_code = pMsg->data.request.basic_service & 0xff;
  erase_cmd_parms->basic_service.code_type = pMsg->data.request.basic_service >> 16; /*BS_CODE or TS_CODE*/
  erase_cmd_parms->basic_service.present = \
    (erase_cmd_parms->basic_service.code_type == NO_CODE )? FALSE:TRUE;

  /* send the command to the CM command queue */
  if(cm_sups_cmd_erase( OEMSUPPS_CmdCb, NULL, client_sups, erase_cmd_parms) == FALSE)
  {
    /*no more resources in cm*/
    FREE(erase_cmd_parms);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(erase_cmd_parms);

  return SUCCESS;

}

/*===========================================================================

FUNCTION OEMSUPPS_ActivateSS

DESCRIPTION
  Send an ActivateSS request

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_ActivateSS(AEETSuppsMessage *pMsg )
{
  cm_act_ss_params_s_type     *act_cmd_parms = (cm_act_ss_params_s_type*)MALLOC(sizeof(cm_act_ss_params_s_type));

  MSG_HIGH("OEMSUPPS_ActivateSS Called",0,0,0);

  if(act_cmd_parms == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }
  /* set all the fields of the Activate SS request */
  act_cmd_parms->ss_ref = (uint8)ISuppsTransObj->m_transId;

  /* ss code */
  
  act_cmd_parms->ss_code = (uint8)pMsg->data.request.code;

   /* basic service group information */
  act_cmd_parms->basic_service.bs_code = pMsg->data.request.basic_service & 0xff;
  act_cmd_parms->basic_service.code_type = pMsg->data.request.basic_service >> 16; /*BS_CODE or TS_CODE*/
  act_cmd_parms->basic_service.present = \
    (act_cmd_parms->basic_service.code_type == NO_CODE )? FALSE:TRUE;

  /* send the command to the CM command queue */
   if (cm_sups_cmd_activate( OEMSUPPS_CmdCb,  NULL, client_sups,act_cmd_parms) == FALSE)
   {
     /*no more resources in cm*/
     FREE(act_cmd_parms);
     MSG_ERROR("No Resources in CM",0,0,0);
     return EFAILED;
   }
   FREE(act_cmd_parms);
   return SUCCESS;
}
/*===========================================================================

FUNCTION OEMSUPPS_DeactivateSS

DESCRIPTION
  Send a DeactivateSS request

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_DeactivateSS ( AEETSuppsMessage *pMsg)
{
  cm_deact_ss_params_s_type     *deact_cmd_parms  = (cm_deact_ss_params_s_type*)MALLOC(sizeof(cm_deact_ss_params_s_type));

  MSG_HIGH("OEMSUPPS_DeactivateSS Called",0,0,0);

  if(deact_cmd_parms == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }

  /* set all the fields of the Deactivate SS request */
  deact_cmd_parms->ss_ref = (uint8)ISuppsTransObj->m_transId;

  /* ss code */
  deact_cmd_parms->ss_code = (uint8)pMsg->data.request.code;

   /* basic service group information */
  deact_cmd_parms->basic_service.bs_code = pMsg->data.request.basic_service & 0xff;
  deact_cmd_parms->basic_service.code_type = pMsg->data.request.basic_service >> 16; /*BS_CODE or TS_CODE*/
  deact_cmd_parms->basic_service.present = \
    (deact_cmd_parms->basic_service.code_type == NO_CODE )? FALSE:TRUE;

  /* send the command to the CM command queue */
  if (cm_sups_cmd_deactivate( OEMSUPPS_CmdCb, NULL, client_sups , deact_cmd_parms ) == FALSE)
  {
    FREE(deact_cmd_parms);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(deact_cmd_parms);
  return SUCCESS;
}
/*===========================================================================

FUNCTION OEMSUPPS_InterrogateSS

DESCRIPTION
  Send an InterrogateSS request

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_InterrogateSS ( AEETSuppsMessage *pMsg)
{

  cm_interr_ss_params_s_type       *interr_cmd_parms = (cm_interr_ss_params_s_type*)MALLOC(sizeof(cm_interr_ss_params_s_type));


  MSG_HIGH("OEMSUPPS_InterrogateSS Called",0,0,0);

  if(interr_cmd_parms == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }

  /* set all the fields of the Interrogate SS request */
  interr_cmd_parms->ss_ref = (uint8)ISuppsTransObj->m_transId;

  /* ss code */
  interr_cmd_parms->ss_code = (uint8)pMsg->data.request.code;

   /* basic service group information */
  interr_cmd_parms->basic_service.bs_code = pMsg->data.request.basic_service & 0xff;
  interr_cmd_parms->basic_service.code_type = pMsg->data.request.basic_service >> 16; /*BS_CODE or TS_CODE*/
  interr_cmd_parms->basic_service.present = \
    (interr_cmd_parms->basic_service.code_type == NO_CODE )? FALSE:TRUE;


  /* send the command to the CM command queue */
  if (cm_sups_cmd_interrogate( OEMSUPPS_CmdCb, NULL, client_sups, interr_cmd_parms ) == NULL)
  {
    FREE(interr_cmd_parms);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(interr_cmd_parms);
  return SUCCESS;

}
/*===========================================================================

FUNCTION OEMSUPPS_RegPwd

DESCRIPTION
  Send a RegisterPassword SS request

DEPENDENCIES


SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_RegPwd( AEETSuppsMessage *pMsg )
{
  cm_reg_pwd_params_s_type       *reg_pwd_cmd_parms = (cm_reg_pwd_params_s_type*)MALLOC(sizeof(cm_reg_pwd_params_s_type));

  MSG_HIGH("OEMSUPPS_RegPwd Called",0,0,0);

  if(reg_pwd_cmd_parms == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }

  /* set all the fields of the request */
  reg_pwd_cmd_parms->ss_ref = (uint8)ISuppsTransObj->m_transId;

  /* SS code */
  reg_pwd_cmd_parms->ss_code.present = TRUE;

  reg_pwd_cmd_parms->ss_code.ss_code = (uint8)pMsg->data.request.code;

  /* Old Password */
  if( pMsg->data.request.req.passwd.szCurPasswd[0] != '\0')
  {
    STRCPY(reg_pwd_cmd_parms->ss_old_pwd.ss_password, pMsg->data.request.req.passwd.szCurPasswd);
    reg_pwd_cmd_parms->ss_old_pwd.present = TRUE;
  }
  else
    reg_pwd_cmd_parms->ss_old_pwd.present = FALSE;


  /* New Password */
  if( pMsg->data.request.req.passwd.szNewPasswd[0] != '\0')
  {
    (void)STRCPY(reg_pwd_cmd_parms->ss_new_pwd.ss_password, pMsg->data.request.req.passwd.szNewPasswd);
        
    reg_pwd_cmd_parms->ss_new_pwd.present = TRUE;

  }
  else
    reg_pwd_cmd_parms->ss_new_pwd.present = FALSE;

  /* New Password Again*/
  if( pMsg->data.request.req.passwd.szNewPasswdRepeated[0] != '\0')
  {
    (void)STRCPY(reg_pwd_cmd_parms->ss_new_pwd_again.ss_password, pMsg->data.request.req.passwd.szNewPasswdRepeated);
    
    reg_pwd_cmd_parms->ss_new_pwd_again.present = TRUE;
  }
  else
    reg_pwd_cmd_parms->ss_new_pwd_again.present = FALSE;

  
  /* send the command to the CM command queue */
  if (cm_sups_cmd_reg_password( OEMSUPPS_CmdCb,  NULL, client_sups, reg_pwd_cmd_parms) == FALSE)
  {
    FREE(reg_pwd_cmd_parms);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(reg_pwd_cmd_parms);
  return SUCCESS;
}

/*===========================================================================

FUNCTION OEMSUPPS_USSReq

DESCRIPTION
  Send a ProcessUnstructured SS request

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_USSReq ( AEETSuppsMessage *pMsg)
{

  cm_uss_params_s_type    *uss_cmd_parms = (cm_uss_params_s_type*)MALLOC(sizeof(cm_uss_params_s_type));
  byte                    num_bytes;
  int                     num_bits = 0;

  MSG_HIGH("OEMSUPPS_USSReq Called",0,0,0);

  if(uss_cmd_parms == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }



  /* set all the fields of the Process USS request */
  uss_cmd_parms->ss_ref = (uint8)ISuppsTransObj->m_transId;

  /* USS Data */

  uss_cmd_parms->uss_data.present = TRUE;

  uss_cmd_parms->uss_data.uss_data_coding_scheme = OEMSUPPS_USS_DEF_ALPHABET_LANG_UNSPEC;

  (void)STRCPY((char*)uss_cmd_parms->uss_data.ussData,
               pMsg->data.request.req.ussd.data);

  num_bits = (int)( STRLEN( (char *)(uss_cmd_parms->uss_data.ussData) ) * 7 ) ;

  num_bytes = (byte)num_bits / 8;

  if( (  num_bits % 8 ) != 0 )
    num_bytes ++;

  uss_cmd_parms->uss_data.size = num_bytes;

  /* send the command to the CM command queue */
  if( cm_sups_cmd_process_uss( OEMSUPPS_CmdCb, NULL, client_sups, uss_cmd_parms) == FALSE)
  {
    FREE(uss_cmd_parms);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(uss_cmd_parms);
  return SUCCESS;
}

/*===========================================================================

FUNCTION OEMSUPPS_ReleaseSS

DESCRIPTION
  Send a ReleaseSS request

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_ReleaseSS(uint8 invoke_id, AEETSuppsNetworkIndType operation)
{
  cm_release_ss_params_s_type  *release_cmd_parms = (cm_release_ss_params_s_type*)MALLOC(sizeof(cm_release_ss_params_s_type));

  MSG_HIGH("OEMSUPPS_ReleaseSS Called",0,0,0);

  if(release_cmd_parms == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }

  /* set the ss operation to be released */
  release_cmd_parms->ss_oper = operation;

  /* set the invocation id */
  //?? How would the user about the request?
  /*if( operation == AEESUPPS_REL_USS  || operation == AEETSUPPS_RES_PASSWD)
    release_cmd_parms->ss_ref = invoke_id;
  else
    release_cmd_parms->ss_ref = (uint8)ISuppsTransObj->m_transId;*/


  /* send the command to the CM */
  if (cm_sups_cmd_release( OEMSUPPS_CmdCb, NULL, client_sups, release_cmd_parms) == FALSE)
  {
    FREE(release_cmd_parms);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(release_cmd_parms);
  return SUCCESS;
}
/*===========================================================================

FUNCTION OEMSUPPS_PwdRes

DESCRIPTION
  Send a Get Password Response

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_PwdRes( AEETSuppsResponse *ss_resp)
{
  cm_get_pwd_res_params_s_type       *get_pwd_res = (cm_get_pwd_res_params_s_type*)MALLOC(sizeof(cm_get_pwd_res_params_s_type));

  MSG_HIGH("OEMSUPPS_PwdRes Called",0,0,0);

  if(get_pwd_res == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }

  /* Invoke ID */
  get_pwd_res->invoke_id = (uint8)ISuppsTransObj->m_InvokeId;

  /* Password */
  (void)STRCPY(get_pwd_res->ss_pwd.ss_password, ss_resp->response_data.data);
  get_pwd_res->ss_pwd.present = TRUE;


  /* send the command to the CM command queue */
  if (cm_sups_cmd_get_password_res( OEMSUPPS_CmdCb, NULL, client_sups, get_pwd_res) == FALSE)
  {
    FREE(get_pwd_res);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(get_pwd_res);
  return SUCCESS;

}

/*===========================================================================

FUNCTION OEMSUPPS_USSRes

DESCRIPTION
  Send an Unstructured SS response

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_USSRes(AEETSuppsResponse  *ss_resp)
{

  byte num_bits;
  byte num_bytes;

  cm_uss_res_params_s_type        *uss_res =(cm_uss_res_params_s_type*) MALLOC(sizeof(cm_uss_res_params_s_type));
  char *uss_resp_data             = (char*)MALLOC(MIN(ss_resp->response_data.length +1,AEETSUPPS_MAX_DATA_LEN));

  MSG_HIGH("OEMSUPPS_USSRes Called",0,0,0);
  

  if(uss_res == NULL)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    FREEIF(uss_resp_data);
    return EFAILED;
  }

  if(uss_resp_data == NULL)
  {
    /*No resources*/
    FREE(uss_res);
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }

  /* set all the fields of the USS Response*/
  if( ss_resp->response_type == AEETSUPPS_RES_USS_OK )
  {
    /* uss data */
    uss_res->uss_res_data.data_type = CM_USS_RES_SS_DATA;

    uss_res->uss_res_data.data.uss_data.present = TRUE;
    uss_res->uss_res_data.data.uss_data.uss_data_coding_scheme =
                                              OEMSUPPS_USS_DEF_ALPHABET_LANG_UNSPEC;

    /*lint -esym(713, ss_resp->length) */

    (void)STRCPY(uss_resp_data, ss_resp->response_data.data);

    /* convert the response from ascii to def alphabet */
    cm_util_ascii_to_def_alphabet( uss_res->uss_res_data.data.uss_data.ussData,
                                   (uint8)MIN(ss_resp->response_data.length,AEETSUPPS_MAX_DATA_LEN) ,
                                   (byte*)uss_resp_data );

    num_bits = (uint8)( MIN(ss_resp->response_data.length,AEETSUPPS_MAX_DATA_LEN) * 7 );
    num_bytes = num_bits / 8;
    if( ( num_bits % 8 ) != 0 )
    {
       num_bytes ++;
    }
    /* size */
    uss_res->uss_res_data.data.uss_data.size = num_bytes;
  }
  else
  {
    /* ss_error */

    uss_res->uss_res_data.data_type = CM_USS_RES_SS_ERROR;

    uss_res->uss_res_data.data.cm_ss_error.present = TRUE;

    uss_res->uss_res_data.data.cm_ss_error.error_code_tag = ERROR_CODE_TAG;

    if( ss_resp->response_type == AEETSUPPS_RES_USS_UNKNOWN_ALPHABET )
    {
      uss_res->uss_res_data.data.cm_ss_error.error_code = unknownAlphabet;
    }
    else if ( ss_resp->response_type == AEETSUPPS_RES_USS_BUSY_DISP )
    {
      uss_res->uss_res_data.data.cm_ss_error.error_code = ussd_Busy;
    }
    uss_res->uss_res_data.data.cm_ss_error.parameter.cm_called_barred_error.present = FALSE;

  }

  /* invocation id */
  uss_res->invoke_id = (uint8)ISuppsTransObj->m_InvokeId;

 /* send the command to the CM command queue */
  if (cm_sups_cmd_uss_res( OEMSUPPS_CmdCb, NULL, client_sups, uss_res) == FALSE)
  {
    FREE(uss_res);
    FREE(uss_resp_data);
    MSG_ERROR("No Resources in CM",0,0,0);
    return EFAILED;
  }
  FREE(uss_res);
  FREE(uss_resp_data);
  return SUCCESS;

}
/*===========================================================================

FUNCTION OEMSUPPS_USSNotifyRes

DESCRIPTION
  Send an Unstructured SS Notify response

DEPENDENCIES

SIDE EFFECTS
  None.

===========================================================================*/
static int OEMSUPPS_USSNotifyRes(AEETSuppsResponse  *ss_resp)
{

  cm_uss_notify_res_params_s_type        *uss_notify_res = (cm_uss_notify_res_params_s_type*)MALLOC(sizeof(cm_uss_notify_res_params_s_type));

  MSG_HIGH("OEMSUPPS_USSNotifyRES Called",0,0,0);

  if(!uss_notify_res)
  {
    /*No resources*/
    MSG_ERROR("No Resources in ISuppsTrans",0,0,0);
    return EFAILED;
  }

  /*Send Appropriate Error Messages is response from Client is not OK*/
  if( ss_resp->response_type == AEETSUPPS_RES_USS_UNKNOWN_ALPHABET )
  {
    uss_notify_res->ss_error.present = TRUE;

    uss_notify_res->ss_error.error_code = unknownAlphabet;

    uss_notify_res->ss_error.error_code_tag = ERROR_CODE_TAG;
  }
  else if (ss_resp->response_type == AEETSUPPS_RES_USS_BUSY_DISP )
  {

    uss_notify_res->ss_error.present = TRUE;

    uss_notify_res->ss_error.error_code = ussd_Busy;

    uss_notify_res->ss_error.error_code_tag = ERROR_CODE_TAG;
  }

  /*Send OK Response*/
  else if ( ss_resp->response_type == AEETSUPPS_RES_USS_OK )
  {
   uss_notify_res->ss_error.present = FALSE;

  }
  
  /* invoke-id */
  uss_notify_res->invoke_id = (uint8)ISuppsTransObj->m_InvokeId;

  if (cm_sups_cmd_uss_notify_res( OEMSUPPS_CmdCb, NULL, client_sups, uss_notify_res) == FALSE)
  {
     FREE(uss_notify_res);
     return EFAILED;
  }
  FREE(uss_notify_res);
  return SUCCESS;

}
#endif


