view src/g23m-gsm/sim/sim_stk.c @ 254:cae495752cf7

top README: update for the FCDEV3B
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 03 Aug 2017 19:18:16 +0000
parents 27a4235405c6
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :  GSM-F&D (8411)
|  Modul   :  SIM_STK
+-----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
|  Purpose :  This modul defines the SIM Toolkit Upgrade.
+-----------------------------------------------------------------------------
*/

#ifndef SIM_STK_C
#define SIM_STK_C

#define ENTITY_SIM

/*==== INCLUDES ===================================================*/

#include <string.h>
#include "typedefs.h"
#include "pcm.h"
#include "pconst.cdg"
#include "message.h"
#include "ccdapi.h"
#include "vsi.h"
#include "custom.h"
#include "gsm.h"
#include "cnf_sim.h"
#include "mon_sim.h"
#include "prim.h"
#include "pei.h"
#include "tok.h"
#include "sim.h"
#include "sim_em.h"
#include "cl_imei.h"  /* IMEI common library */
#include "cl_shrd.h"

#ifdef TI_PS_UICC_CHIPSET_15
#include "8010_136_SIMDRV_SAP_inline.h"
#endif

EXTERN  USHORT   stk_l_cmd;
/*==== EXPORT =====================================================*/

/*
*  These Functions are only temporary valid and should be replaced as soon as possible
*/
EXTERN UBYTE get_network_meas   (UBYTE * chan_list);
EXTERN UBYTE get_bcch_chan_list (stk_data_type * out_stk_data);


/*==== PRIVAT =====================================================*/

#ifdef FF_SAT_E
LOCAL void stk_handle_ccd_error(UBYTE notOK,
                                UBYTE* status,
                                UBYTE* general_result,
                                UBYTE* add_info_result);
LOCAL void stk_bip_decode_stk_command(T_sdu*          message,
                                      T_cmd_details*  cmd_details,
                                      UBYTE*          status,
                                      UBYTE*          general_result,
                                      UBYTE*          add_info_result);
LOCAL void stk_close_dti_connection(UBYTE open);
LOCAL void stk_close_bip_channel(UBYTE general_result,
                                 UBYTE add_info_result);
/* LOCAL void stk_dti_inform_mmi_old (UBYTE dti_conn_req); */
LOCAL void stk_dti_inform_mmi(UBYTE dti_conn_req, UBYTE bip_conn_req );

LOCAL void stk_dti_send_data();
LOCAL void stk_bip_send_data_terminal_response(UBYTE general_result,
                                               UBYTE add_info_result);
#endif /* FF_SAT_E */

/*==== TYPES ======================================================*/

typedef struct
{
    UBYTE tag;
    UBYTE min_len;
    UBYTE mand;
    UBYTE min_req;
} T_SAT_TAG_DESC;

typedef struct
{
    UBYTE cmd_type;
    UBYTE tp_i;
    UBYTE tp_flag;
    UBYTE max_tag;
    const T_SAT_TAG_DESC *tag_desc;
} T_SAT_CMD_DESC;

/*==== CONSTANTS ==================================================*/

const T_SAT_TAG_DESC sat_def_cmd[2] = {
  { STK_COMMAND_DETAILS_TAG,
    STK_COMMAND_DETAILS_LEN,
    TRUE, TRUE },
  { STK_DEVICE_IDENTITY_TAG,
    STK_DEVICE_IDENTITY_LEN,
    TRUE, TRUE }
};                   // valid tags for any command

const T_SAT_TAG_DESC sat_cmd_poll_itv[3] = {
  { STK_COMMAND_DETAILS_TAG,
    STK_COMMAND_DETAILS_LEN,
    TRUE, TRUE },
  { STK_DEVICE_IDENTITY_TAG,
    STK_DEVICE_IDENTITY_LEN,
    TRUE, TRUE },
  { STK_DURATION_TAG,
    STK_DURATION_LEN,
    TRUE, TRUE }
};                   // valid tags for POLL INTERVALL

const T_SAT_TAG_DESC sat_cmd_refresh[3] = {
  { STK_COMMAND_DETAILS_TAG,
    STK_COMMAND_DETAILS_LEN,
    TRUE, TRUE },
  { STK_DEVICE_IDENTITY_TAG,
    STK_DEVICE_IDENTITY_LEN,
    TRUE, TRUE },
  { STK_FILE_LIST_TAG,
    STK_FILE_LIST_LEN,
    FALSE, TRUE }
};                  // valid tags for REFRESH

const T_SAT_TAG_DESC sat_cmd_event_list[3] = {
  { STK_COMMAND_DETAILS_TAG,
    STK_COMMAND_DETAILS_LEN,
    TRUE, TRUE },
  { STK_DEVICE_IDENTITY_TAG,
    STK_DEVICE_IDENTITY_LEN,
    TRUE, TRUE },
  { STK_EVENT_LIST_TAG,
    STK_EVENT_LIST_LEN,
    TRUE, TRUE }
};                  // valid tags for SETUP EVENT LIST

const T_SAT_TAG_DESC sat_cmd_timer[4] = {
  { STK_COMMAND_DETAILS_TAG,
    STK_COMMAND_DETAILS_LEN,
    TRUE, TRUE },
  { STK_DEVICE_IDENTITY_TAG,
    STK_DEVICE_IDENTITY_LEN,
    TRUE, TRUE },
  { STK_TIMER_ID_TAG,
    STK_TIMER_ID_LEN,
    TRUE, TRUE },
  { STK_TIMER_VALUE_TAG,
    STK_TIMER_VALUE_LEN,
    FALSE, FALSE }
};                  // valid tags for TIMER MANAGEMENT

const T_SAT_TAG_DESC sat_cmd_receive_data[5] = {
  { STK_COMMAND_DETAILS_TAG,
    STK_COMMAND_DETAILS_LEN,
    TRUE, TRUE },
  { STK_DEVICE_IDENTITY_TAG,
    STK_DEVICE_IDENTITY_LEN,
    TRUE, TRUE },
  { STK_ALPHA_IDENTITY_TAG,
    STK_ALPHA_IDENTITY_LEN,
    FALSE, FALSE },
  { STK_ICON_IDENTITY_TAG,
    STK_ICON_IDENTITY_LEN,
    FALSE, FALSE },
  { STK_CHANNEL_DATA_LGTH_TAG,
    STK_CHANNEL_DATA_LGTH_LEN,
    TRUE, TRUE }
};                  // valid tags for RECEIVE DATA

const T_SAT_TAG_DESC sat_cmd_send_data[5] = {
  { STK_COMMAND_DETAILS_TAG,
    STK_COMMAND_DETAILS_LEN,
    TRUE, TRUE },
  { STK_DEVICE_IDENTITY_TAG,
    STK_DEVICE_IDENTITY_LEN,
    TRUE, TRUE },
  { STK_ALPHA_IDENTITY_TAG,
    STK_ALPHA_IDENTITY_LEN,
    FALSE, FALSE },
  { STK_ICON_IDENTITY_TAG,
    STK_ICON_IDENTITY_LEN,
    FALSE, FALSE },
  { STK_CHANNEL_DATA_TAG,
    STK_CHANNEL_DATA_LEN,
    TRUE, TRUE }
};                  // valid tags for SEND DATA

const T_SAT_CMD_DESC sat_cmd_list[] = {
  { 0, 0, 0xFF,
    item_of(sat_def_cmd), sat_def_cmd },    // command not yet known
  { STK_REFRESH, 2, SAT_TP3_REFRESH,
    item_of(sat_cmd_refresh), sat_cmd_refresh },
  { STK_MORE_TIME, 2, SAT_TP3_MORE_TIME,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_POLL_INTERVALL, 2, SAT_TP3_POLL_ITV,
    item_of(sat_cmd_poll_itv), sat_cmd_poll_itv },
  { STK_POLLING_OFF, 2, SAT_TP3_POLL_OFF,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SET_UP_CALL, 3, SAT_TP4_SETUP_CALL,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SEND_SS, 3, SAT_TP4_SEND_SS,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SEND_SMS, 3, SAT_TP4_SEND_SMS,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_PLAY_TONE, 2, SAT_TP3_PLAY_TONE,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_DISPLAY_TEXT, 2, SAT_TP3_DSPL_TXT,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_GET_INKEY, 2, SAT_TP3_GET_INKEY,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_GET_INPUT, 2, SAT_TP3_GET_INPUT,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SELECT_ITEM, 3, SAT_TP4_SEL_ITEM,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SET_UP_MENU, 3, SAT_TP4_SETUP_MENU,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_PROVIDE_LOCAL_INFO, 3, SAT_TP4_PLI_PLMN_IMEI,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_TIMER_MANAGEMENT, 7, SAT_TP8_TMNG_ST,
    item_of(sat_cmd_timer), sat_cmd_timer },
  { STK_SETUP_EVENT_LIST, 4, SAT_TP5_EVENT_LIST,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SEND_USSD, 3, SAT_TP4_SEND_USSD,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SEND_DTMF, 8, SAT_TP9_DTMF_CMD,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_SETUP_IDLE_TEXT, 7, SAT_TP8_IDLE_TXT,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_RUN_AT_CMD, 7, SAT_TP8_AT_CMD,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_LANGUAGE_NOTIFICATION, 8, SAT_TP9_LANG_NOTIFY,
    item_of(sat_def_cmd), sat_def_cmd }
#ifdef FF_SAT_C
  ,
  { STK_LAUNCH_BROWSER, 8, SAT_TP9_LAUNCH_BROWSER,
    item_of(sat_def_cmd), sat_def_cmd }
#endif /* FF_SAT_C */
#ifdef FF_SAT_E
  ,
  { STK_OPEN_CHANNEL, 11, SAT_TP12_OPEN_CHANNEL,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_CLOSE_CHANNEL, 11, SAT_TP12_CLOSE_CHANNEL,
    item_of(sat_def_cmd), sat_def_cmd },
  { STK_RECEIVE_DATA, 11, SAT_TP12_RECEIVE_DATA,
    item_of(sat_cmd_receive_data), sat_cmd_receive_data },
  { STK_SEND_DATA, 11, SAT_TP12_SEND_DATA,
    item_of(sat_cmd_send_data), sat_cmd_send_data },
  { STK_GET_CHANNEL_STAT, 11, SAT_TP12_GET_CHANNEL_STAT,
    item_of(sat_def_cmd), sat_def_cmd }
#endif /* FF_SAT_E */
};

/* Terminal Profile bits for which SIM is exclusively responsible.
   They are discarded from the profile provided by MMI */

static const UBYTE sat_tp_sim_exclusive[MAX_STK_PRF] = {
      /* SAT_TP1_PRF_DNL |*/ SAT_TP1_TIMER_EXP | SAT_TP1_CC_ON_REDIAL,
      0x0,
      SAT_TP3_MORE_TIME | SAT_TP3_POLL_ITV | SAT_TP3_POLL_OFF,
      SAT_TP4_PLI_PLMN_IMEI | SAT_TP4_PLI_NMR,
      0x0 /*SAT_TP5_LOC_STATUS*/,
      0x0, 0xFF,
      SAT_TP8_TMNG_ST | SAT_TP8_TMNG_VAL,
      SAT_TP9_BCCH_COD | SAT_TP9_PLI_TIMING_ADV,    /* Timing Advance is to be supported */
      0x0, 0x0,
      SAT_TP12_RECEIVE_DATA | SAT_TP12_SEND_DATA,
      0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0xFF};

/* Terminal Profile bits which have to be supported by SIM to be
   valid with the profile provided by MMI */

static const UBYTE sat_tp_sim_ability[MAX_STK_PRF] = {
      SAT_TP1_PRF_DNL,
      SAT_TP2_CMD_RES,
      SAT_TP3_DSPL_TXT | SAT_TP3_GET_INKEY | SAT_TP3_GET_INPUT
       | SAT_TP3_PLAY_TONE | SAT_TP3_REFRESH,
      SAT_TP4_SEL_ITEM | SAT_TP4_SEND_SMS | SAT_TP4_SEND_SS
       | SAT_TP4_SEND_USSD | SAT_TP4_SETUP_CALL | SAT_TP4_SETUP_MENU,
      SAT_TP5_EVENT_LIST, 0x0, 0x0,
      SAT_TP8_IDLE_TXT | SAT_TP8_AT_CMD | SAT_TP8_PLI_DTT,
      SAT_TP9_DTMF_CMD | SAT_TP9_LANG_NOTIFY | SAT_TP9_LAUNCH_BROWSER,
      0x0, 0x0,
      SAT_TP12_OPEN_CHANNEL | SAT_TP12_CLOSE_CHANNEL | SAT_TP12_GET_CHANNEL_STAT,
      0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

/* Currently supported Terminal Profile bits by SIM */

static const UBYTE sat_tp_sim_enabled[MAX_STK_PRF] = {
      SAT_TP1_PRF_DNL | SAT_TP1_SMS_DNL | SAT_TP1_9E_XX | SAT_TP1_TIMER_EXP,
      SAT_TP2_CMD_RES,
      SAT_TP3_MORE_TIME | SAT_TP3_POLL_ITV | SAT_TP3_POLL_OFF | SAT_TP3_REFRESH,
      SAT_TP4_PLI_PLMN_IMEI | SAT_TP4_PLI_NMR,
      0x0, 0x0, 0x0,
      SAT_TP8_TMNG_ST | SAT_TP8_TMNG_VAL | SAT_TP8_PLI_DTT
       | SAT_TP8_IDLE_TXT | SAT_TP8_AT_CMD,
      SAT_TP9_BCCH_COD | SAT_TP9_PLI_TIMING_ADV,       /* Timing Advance is to be supported */
      0x0, 0x0,
#ifdef FF_SAT_E
      SAT_TP12_OPEN_CHANNEL | SAT_TP12_CLOSE_CHANNEL | SAT_TP12_GET_CHANNEL_STAT
       | SAT_TP12_RECEIVE_DATA | SAT_TP12_SEND_DATA,
#else
      0x0,
#endif
      0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

static const UBYTE tbl_device_src_id[] =
{
  DEV_SRC_KBD,
  DEV_SRC_DSP,
  DEV_SRC_EAR,
  DEV_SRC_CDR0,
  DEV_SRC_CDR1,
  DEV_SRC_CDR2,
  DEV_SRC_CDR3,
  DEV_SRC_CDR4,
  DEV_SRC_CDR5,
  DEV_SRC_CDR6,
  DEV_SRC_CDR7,
  DEV_SRC_CH1,
  DEV_SRC_CH2,
  DEV_SRC_CH3,
  DEV_SRC_CH4,
  DEV_SRC_CH5,
  DEV_SRC_CH6,
  DEV_SRC_CH7,
  DEV_SRC_SIM,
  DEV_SRC_ME,
  DEV_SRC_NTW,
  0
};

/*==== VARIABLES ==================================================*/
BOOL startTimerPollOff = FALSE; 

USHORT cusSatMinPollItv = 50;     // 5 seconds

/*==== FUNCTIONS ==================================================*/

LOCAL UBYTE stk_dti_bip_receive_data (T_sdu* message, UBYTE result_code);

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_init_sim_data          |
+--------------------------------------------------------------------+

  PURPOSE : Initialize the SIM data for the module SIM TOOLKIT.

*/

GLOBAL void stk_init_sim_data (void)
{
  TRACE_FUNCTION ("stk_init_sim_data()");

  /*
   * initialize SAT variables
   */
  sim_data.sat_session    = FALSE;
  sim_data.ext_sat_cmd    = FALSE;
  sim_data.term_resp_sent = FALSE;
  sim_data.chk_sat_avail  = FALSE;
  sim_data.context_switch_ptr         = NULL; 
  sim_data.cust_mode                  = FALSE;
  sim_data.user_confirmation_expected = FALSE;

#ifdef FF_SAT_E
  /*
   * initialize DTI variables
   */
  sim_data.dti_connection_state       = SIM_DTI_CONNECTION_CLOSED;
  sim_data.dti_rx_state               = SIM_DTI_RX_IDLE;
  sim_data.dti_tx_state               = SIM_DTI_TX_IDLE;
  sim_data.event_data_avail           = SIM_EVENT_DISABLE;
  sim_data.bip_state                  = SIM_BIP_CLOSED;
  sim_data.bip_suspend                = FALSE;
#ifdef _SIMULATION_
  TRACE_EVENT("bip_rx_state = IDLE");
#endif
  sim_data.bip_rx_state               = SIM_BIP_RX_IDLE;
#ifdef _SIMULATION_
  TRACE_EVENT("bip_tx_state = IDLE");
#endif
  sim_data.bip_tx_state               = SIM_BIP_TX_IDLE;
  sim_data.bip_timer_state            = SIM_BIP_TIMER_DISCONNECTED;
  sim_data.bip_release_time           = SIM_NO_AUTO_RELEASE;
  sim_data.bip_general_result         = RSLT_PERF_SUCCESS;
  sim_data.bip_add_info_result        = ADD_NO_CAUSE;
  sim_data.con_type                   = SIM_CON_TYPE_UDP;
  sim_data.data_to_send.first         = (ULONG)NULL;
  sim_data.data_to_send.list_len      = 0;
  sim_data.prev_data_to_send.first    = (ULONG)NULL;
  sim_data.prev_data_to_send.list_len = 0;
  sim_data.received_data.first        = (ULONG)NULL;
  sim_data.received_data.list_len     = 0;
  sim_data.received_data_pos          = 0;
  sim_data.sim_dti_req                = NULL;
  sim_data.sim_bip_req                = NULL;
  sim_data.sim_bip_config_req         = NULL;
  memset(&sim_data.udp_parameters, 0, sizeof(T_SRC_DES));
#endif /* FF_SAT_E */
} /* stk_init_sim_data() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)     MODULE  : SIM_STK                      |
| STATE   : code              ROUTINE : stk_check_tp                 |
+--------------------------------------------------------------------+

  PURPOSE : Evaluates the received Terminal Profile against the
            capability of the SIM Entity.

*/

GLOBAL void stk_check_tp (UBYTE *out_prf, UBYTE *in_prf, USHORT len)
{
  int i;
  UBYTE tp_tmp;

/* TRACE_FUNCTION ("stk_check_tp()"); */

  len = MINIMUM(len, MAX_STK_PRF);
  for (i = 0; i < len; i++)                 // check TP from MMI
  {
#ifndef __OLD
    tp_tmp = sat_tp_sim_enabled[i] & ~sat_tp_sim_ability[i];
    out_prf[i] = ((in_prf[i] & ~sat_tp_sim_exclusive[i]) &
                 ~tp_tmp) | tp_tmp;
#else
    out_prf[i] = ((in_prf[i] & ~sat_tp_sim_exclusive[i]) &
                  (sat_tp_sim_enabled[i] | ~sat_tp_sim_ability[i]))
                  | sat_tp_sim_enabled[i];
#endif
  }
  if (!(out_prf[0] & SAT_TP1_SMS_DNL))      // check SMS download
    out_prf[0] &= ~SAT_TP1_9E_XX;           // only valid with SMS download

  if (len >= 6 AND
      !(out_prf[4] & SAT_TP5_EVENT_LIST))   // check event list consistency
    out_prf[5] = out_prf[4] = 0;            // discard event list

  if (len >= 12 AND
      (out_prf[11] & STK_TP12_CLASS_E) NEQ STK_TP12_CLASS_E)
  {
    out_prf[11] &= ~STK_TP12_CLASS_E;

    if (len >= 13)
      out_prf[12] &= ~(SAT_TP13_CSD_SUPP_BY_ME | SAT_TP13_GPRS_SUPP_BY_ME);

    if (len >= 17)
      out_prf[16] &= ~(SAT_TP17_BEARER_IND_SUPP_TCP | SAT_TP17_BEARER_IND_SUPP_UDP);
  }
  TRACE_EVENT_P5("TP: %02X %02X %02X %02X ... (%d bytes)",
                 out_prf[0], out_prf[1], out_prf[2], out_prf[3], len);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)     MODULE  : SIM_STK                      |
| STATE   : code              ROUTINE : stk_perform_profile_download |
+--------------------------------------------------------------------+

  PURPOSE : Initialize the SIM data for the module application.

*/

GLOBAL void stk_perform_profile_download (void)
{
  USHORT result;
  USHORT used_tp = (USHORT)sizeof (sim_data.stk_profile);

  TRACE_FUNCTION ("stk_perform_profile_download()");

  do
  {
    if (sim_data.stk_profile[--used_tp] NEQ 0)
      break;
  } while (used_tp >= 3);
  used_tp++;

  if ((result = FKT_TerminalProfile (sim_data.stk_profile,
                                     used_tp)) NEQ SIM_NO_ERROR)
  {
    TRACE_EVENT_P1("TP dnl error: %04X", result);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)     MODULE  : SIM_STK                      |
| STATE   : code              ROUTINE : stk_proactive_polling        |
+--------------------------------------------------------------------+

  PURPOSE : Polling of an proactive SIM card.

*/

static const UBYTE tag_dur [] =
{
    STK_DURATION_TAG |
    STK_COMPREHENSION_REQUIRED,     /* duration tag                 */
    STK_DURATION_LEN,               /* duration length              */
    0,                              /* unit                         */
    0                               /* number of units              */
};

static const UBYTE terminal_response_loci [21]  =
{
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,     /* command details tag          */
    STK_COMMAND_DETAILS_LEN,        /* command details length       */
    0,                              /* command number               */
    STK_PROVIDE_LOCAL_INFO,         /* command PROVIDE LOCATION INFO*/
    0,                              /* location information         */
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /* device details tag           */
    STK_DEVICE_IDENTITY_LEN,        /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED,     /* result tag                   */
    1,                              /* result length                */
    0,                              /* result OK                    */
    0x13,                           /* location information tag     */
    7,                              /* location information length  */
    0,0,0,                          /* MCC & MNC                    */
    0,0,                            /* Location area code           */
    0,0                             /* cell identity                */
};

static const UBYTE terminal_response_imei [22]  =
{
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,     /* command details tag          */
    STK_COMMAND_DETAILS_LEN,        /* command details length       */
    0,                              /* command number               */
    STK_PROVIDE_LOCAL_INFO,         /* command PROVIDE LOCATION INFO*/
    1,                              /* imei                         */
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /* device details tag           */
    STK_DEVICE_IDENTITY_LEN,        /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED,     /* result tag                   */
    1,                              /* result length                */
    0,                              /* result OK                    */
    0x14,                           /* imei tag                     */
    8,                              /* imei length                  */
    0,0,0,0,0,0,0,0                 /* imei digits                  */
};

static const UBYTE terminal_response_nmr [14]  =
{
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,     /* command details tag          */
    STK_COMMAND_DETAILS_LEN,        /* command details length       */
    0,                              /* command number               */
    STK_PROVIDE_LOCAL_INFO,         /* command PROVIDE LOCATION INFO*/
    2,                              /* network measurement results  */
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /* device details tag           */
    STK_DEVICE_IDENTITY_LEN,        /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED,     /* result tag                   */
    1,                              /* result length                */
    0,                              /* result OK                    */
    0x16,                           /* nmr tag                      */
    16                              /* nmr length                   */
};

/*
 * Terminal-Response for timing advance
 */
static const UBYTE terminal_response_timingadv [16]  =
{
    /* ---- cmd details ----- */
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,   /*  command details tag  */
    STK_COMMAND_DETAILS_LEN,      /*  command details length  */
    0,                            /*  command number  */
    STK_PROVIDE_LOCAL_INFO,       /*  command PROVIDE LOCAL INFO  */
    5,                            /*  timing advance  */

    /* ---- device ids ------ */
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /*  device details tag  */
    STK_DEVICE_IDENTITY_LEN,        /*  device details length  */
    0x82,                           /*  source ME  */
    0x81,                           /*  destination SIM  */
    
    /* ------result --------- */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED,     /*  result tag  */
    1,                              /*  result length  */
    0,                              /*  result OK  */
    
    /* --- timing advance --- */
    0x2E,                           /*  timing advance tag  */
    2,                              /*  timing advance len  */
    0,                              /*  ME Status  */
    0                               /*  Timing Advance  */
};

static const T_SIM_TRSP_SIMPLE terminal_response_def =
{
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,     /* command details tag          */
    STK_COMMAND_DETAILS_LEN,        /* command details length       */
    0,                              /* command number               */
    0,                              /* command type place holder    */
    0,                              /* command qualifier            */
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /* device details tag           */
    STK_DEVICE_IDENTITY_LEN,        /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED,     /* result tag                   */
    1,                              /* result length place holder   */
    0xFF,                           /* result place holder          */
    0,                              /* result additional info       */
};

#ifdef __INVALID
static const UBYTE terminal_response_ok [12]  =
{
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,     /* command details tag          */
    STK_COMMAND_DETAILS_LEN,        /* command details length       */
    0,                              /* command number               */
    2,                              /* command MORE TIME            */
    0,                              /* not used                     */
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /* device details tag           */
    STK_DEVICE_IDENTITY_LEN,        /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED,     /* result tag                   */
    1,                              /* result length                */
    0                               /* result OK                    */
};

static const UBYTE terminal_response_loci_neg [13]  =
{
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,     /* command details tag          */
    STK_COMMAND_DETAILS_LEN,        /* command details length       */
    0,                              /* command number               */
    STK_PROVIDE_LOCAL_INFO,         /* command PROVIDE LOCATION INFO*/
    0,                              /* location information         */
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /* device details tag           */
    STK_DEVICE_IDENTITY_LEN,        /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED,     /* result tag                   */
    2,                              /* result length                */
    0x20,                           /* result ME unable to process  */
    4                               /* result add. info no service  */
};

static const UBYTE terminal_response_no_cap [12]  =
{
    STK_COMMAND_DETAILS_TAG |
    STK_COMPREHENSION_REQUIRED,     /* command details tag          */
    STK_COMMAND_DETAILS_LEN,        /* command details length       */
    0,                              /* command number               */
    0x26,                           /* command PROVIDE LOCATION INFO*/
    0,                              /* location information         */
    2,                              /* device details tag           */
    2,                              /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    3,                              /* result tag                   */
    1,                              /* result length                */
    0x30                            /* result beyond ME capability  */
};
#endif

LOCAL UBYTE stk_process_tl (UBYTE **pp_stk,
                            SHORT *p_ber_len,
                            SHORT *p_tlv_len)
{
/* get tag and length and adjust pointer to get parameter values */

  UBYTE tag = STK_COMPREHENSION_REQUIRED;
  SHORT tlv_len;

  if (*p_ber_len >= 2)
  {
    tag = *((*pp_stk)++);           // get tag and adjust pointer
    if ((tlv_len = (SHORT)*((*pp_stk)++)) <= 0x7F)
    {                               // one byte length
      *p_tlv_len = tlv_len;         // get length
      *p_ber_len -= 2;
    }
    else if (tlv_len EQ 0x81 AND *p_ber_len >= 3)
    {                               // two bytes length
      *p_tlv_len = (SHORT)*((*pp_stk)++);
      *p_ber_len -= 3;              // get length and adjust pointer
    }
    else
    {                               // erroneous length coding
      *p_tlv_len = 0;
      *p_ber_len = 0;
      return STK_COMPREHENSION_REQUIRED;
    }
  }
  return tag;
}

LOCAL SHORT stk_build_response (UBYTE *p_response,
                                UBYTE *p_cmd, int cmd_len,
                                UBYTE *p_res, int res_len,
                                UBYTE *p_prm, int prm_len)
{
  /*
   * builds a TERMINAL RESPONSE
   */
static const UBYTE dev_resp[5] =
  {
    STK_DEVICE_IDENTITY_TAG |
    STK_COMPREHENSION_REQUIRED,     /* device details tag           */
    STK_DEVICE_IDENTITY_LEN,        /* device details length        */
    0x82,                           /* source ME                    */
    0x81,                           /* destination SIM              */
    STK_RESULT_TAG |
    STK_COMPREHENSION_REQUIRED      /* result tag                   */
  };
  int tr_len = 6;

#ifdef _SIMULATION_
  TRACE_FUNCTION ("stk_build_response()");
#endif
  TRACE_FUNCTION_P1 ("TERMINAL_RESPONSE: result=0x%02X", (int)*p_res);

  memcpy (p_response, p_cmd, cmd_len);
  memcpy (p_response + cmd_len, dev_resp, 5);
  p_response[cmd_len + 5] = (UBYTE)res_len;
  memcpy (p_response + cmd_len + 6, p_res, res_len);
  tr_len += cmd_len + res_len;

  if (p_prm NEQ NULL AND prm_len > 0)
  {
    memcpy (p_response + tr_len, p_prm, prm_len);
    tr_len += prm_len;
  }
  return (SHORT)tr_len;
}


GLOBAL int process_sim_refresh( T_CONTEXT_SWITCH    *cmd_ptr )
{
  int i;
  SHORT resp_len = 0;
  #ifdef TI_PS_UICC_CHIPSET_15
  U8 readerId = SIMDRV_VAL_READER_ID__RANGE_MIN;
  U8 voltageSelect = SIMDRV_REQ_VOLTAGE_SEL;
  #endif
  
  T_STK_POLL_DATA *p;
  MALLOC (p, sizeof (T_STK_POLL_DATA));
  memset (p, 0, sizeof (T_STK_POLL_DATA));


  TRACE_FUNCTION ("process_sim_refresh()");


  /* process as before */
  switch (cmd_ptr->p_cmd[4])
  {
  case 1:
    /*check file list is empty */
    if( ( 0 == cmd_ptr->fl_len ) OR ( 1 == cmd_ptr->fl_len ) )
    {
      cmd_ptr->res_code[0] = STK_RES_ERR_MISS_VALUE;
      resp_len = stk_build_response (p->response,
                                     cmd_ptr->p_cmd, (int)cmd_ptr->cmd_len,
                                     cmd_ptr->res_code, 1, NULL, 0);
#ifdef _SIMULATION_
      TRACE_EVENT("FCN: File List is empty");
#endif
      FKT_TerminalResponse (p->response, (USHORT)resp_len);
      break;
    }
    if (cmd_ptr->tag2 NEQ NULL AND cmd_ptr->fl_len >= 5)
    {
      BOOL sim_init = FALSE;
      PALLOC (file_update_sms, SIM_FILE_UPDATE_IND);
      memset (file_update_sms, 0, sizeof(T_SIM_FILE_UPDATE_IND));

      file_update_sms->val_nr = *(cmd_ptr->tag2++);
      cmd_ptr->fl_len -= 3;    /* align file id count */
      for (i = 0; cmd_ptr->fl_len > 0 AND i < (int)file_update_sms->val_nr; i++)
      {
        do
        {
          cmd_ptr->tag2 += 2;
          /* Check if entry is a first level directory */
          if(cmd_ptr->tag2[0] EQ 0x7F)
          {
            if(file_update_sms->file_info[i].v_path_info EQ FALSE)
            {
              file_update_sms->file_info[i].v_path_info = TRUE;
              file_update_sms->file_info[i].path_info.df_level1 = 
                ((USHORT)cmd_ptr->tag2[0] << 8) | (USHORT)cmd_ptr->tag2[1];
            }
            else
            {
              /* This has already been filled. There cannot be another 
              first level directory. Since i is reduced, i will not 
              equal to file_update_sms->val_nr and error will be sent to SIM */
              i--;
              break;
            }
          }
          /* Check if entry is a second level directory and first level 
           * directory is also filled*/
          else if(cmd_ptr->tag2[0] EQ 0x5F)
          { 
            if(file_update_sms->file_info[i].v_path_info EQ TRUE AND
               file_update_sms->file_info[i].path_info.v_df_level2 EQ FALSE)
            {
              file_update_sms->file_info[i].path_info.v_df_level2 = TRUE;
              file_update_sms->file_info[i].path_info.df_level2 = 
                ((USHORT)cmd_ptr->tag2[0] << 8) | (USHORT)cmd_ptr->tag2[1];
            }
            else
            {
              /* This has already been filled. There cannot be another 
              second level directory */
              i--;
              break;
            }
          }
          cmd_ptr->fl_len -= 2;
        }
        while (cmd_ptr->fl_len > 0 AND cmd_ptr->tag2[2] NEQ 0x3F);

        if (cmd_ptr->tag2[0] NEQ 0x2F AND cmd_ptr->tag2[0] NEQ 0x6F
                AND cmd_ptr->tag2[0] NEQ 0x4F)
          break;      /* no EF code -> loop exit leads to error response */

        file_update_sms->file_info[i].datafield = ((USHORT)cmd_ptr->tag2[0] << 8)
                                                   | (USHORT)cmd_ptr->tag2[1];
        if ((file_update_sms->file_info[i].datafield EQ SIM_PHASE) OR
            (file_update_sms->file_info[i].datafield EQ SIM_SST))

        {             /* SIM initialisation is needed! */
           sim_init = TRUE;
           TRACE_FUNCTION ("FCN converted to INIT");
           /* break;      exit for loop */
        }
      }
      if (cmd_ptr->fl_len > 0 OR i NEQ (int)file_update_sms->val_nr)
      {               /* inconsistent TLV content */
        PFREE(file_update_sms);
        cmd_ptr->res_code[0] = STK_RES_ERR_CMD_DATA;
        resp_len = stk_build_response (p->response,
                            cmd_ptr->p_cmd, (int)cmd_ptr->cmd_len,
                            cmd_ptr->res_code, 1, NULL, 0);
#ifdef _SIMULATION_
        TRACE_EVENT("FCN: inconsistent TLV content");
#endif
        FKT_TerminalResponse (p->response, (USHORT)resp_len);
        break;        /* exit switch 'cmd_qual' */
      }
      if (!sim_init)
      {
        {
          PALLOC (file_update_mmi, SIM_FILE_UPDATE_IND);
          memcpy (file_update_mmi, file_update_sms,
                         sizeof(T_SIM_FILE_UPDATE_IND));
          PSENDX (MMI, file_update_mmi);
        }
        {
          PALLOC (file_update_mm, SIM_FILE_UPDATE_IND);
          memcpy (file_update_mm, file_update_sms,
                         sizeof(T_SIM_FILE_UPDATE_IND));
          PSENDX (MM, file_update_mm);
        }
        PSENDX (SMS, file_update_sms);

        sim_data.file_change_resp = 0x7;  /* check response */
        /* Force file selection */
        sim_data.act_directory = NOT_PRESENT_16BIT;
        sim_data.act_field     = NOT_PRESENT_16BIT;

        if ((USHORT)(cmd_ptr->cmd_len + 7) <= sizeof (sim_data.stk_response))
        {
          sim_data.stk_resp_len = stk_build_response (sim_data.stk_response,
                                      cmd_ptr->p_cmd, (int)cmd_ptr->cmd_len,
                                      cmd_ptr->res_code, 1, NULL, 0);
#ifdef _SIMULATION_
          TRACE_EVENT("FCN: prepare TR");
#endif
        }
        else
          sim_data.stk_resp_len = 0;
        break;
      }
      else
      {
        PFREE (file_update_sms);
      }
    }
    else
    {
      cmd_ptr->res_code[0] = STK_RES_ERR_MISS_VALUE;
      resp_len = stk_build_response (p->response,
                                     cmd_ptr->p_cmd, (int)cmd_ptr->cmd_len,
                                     cmd_ptr->res_code, 1, NULL, 0);
#ifdef _SIMULATION_
      TRACE_EVENT("FCN: cmd incomplete");
#endif
      FKT_TerminalResponse (p->response, (USHORT)resp_len);
      break;
    }           // no break for sim_init EQ TRUE !

  case 3:
  case 2:
    if (cmd_ptr->res_code[0] EQ STK_RES_SUCCESS)
      // do not overwrite special result codes
      // these commands read more EFs than indicated
      cmd_ptr->res_code[0] = STK_RES_SUCC_ADD_EF_READ;
  case 0:
    if ( (SIM_IS_FLAG_SET (CALL_ACTIVE)) AND (sim_data.cust_mode EQ 0) )
    {
      cmd_ptr->res_code[0] = STK_RES_BUSY_ME;
      cmd_ptr->res_code[1] = STK_RES_EXT_BUSY_CALL;
      resp_len = stk_build_response (p->response,
                                     cmd_ptr->p_cmd, (int)cmd_ptr->cmd_len,
                                     cmd_ptr->res_code, 2, NULL, 0);
#ifdef _SIMULATION_
      TRACE_EVENT("INIT: call active");
#endif
      FKT_TerminalResponse (p->response, (USHORT)resp_len);
    }
    else
    {
      /* Force file selection */
      sim_data.act_directory = NOT_PRESENT_16BIT;
      sim_data.act_field     = NOT_PRESENT_16BIT;
      sim_data.status_time   = THIRTY_SECONDS;
      app_sim_read_parameters ();
      /* The terminal response to be sent is created and stored in context.
         Once ACI and MM indicates the completion of the reading of the EFs
         through SIM_SYNC_REQ, the response will be sent. */
      sim_data.stk_resp_len = stk_build_response (sim_data.stk_response,
                                     cmd_ptr->p_cmd, (int)cmd_ptr->cmd_len,
                                     cmd_ptr->res_code, 1, NULL, 0);
      sim_data.sync_awaited = SIM_SYNC_AWAIT_MM_READ | SIM_SYNC_AWAIT_MMI_READ;

#ifdef _SIMULATION_
      TRACE_EVENT("INIT: success");
#endif
    }
    break;
  case 4:
    if ( (SIM_IS_FLAG_SET (CALL_ACTIVE)) AND (sim_data.cust_mode EQ 0) )
    {
      cmd_ptr->res_code[0] = STK_RES_BUSY_ME;
      cmd_ptr->res_code[1] = STK_RES_EXT_BUSY_CALL;
      resp_len = stk_build_response (p->response,
                                     cmd_ptr->p_cmd, (int)cmd_ptr->cmd_len,
                                     cmd_ptr->res_code, 2, NULL, 0);
#ifdef _SIMULATION_
      TRACE_EVENT("RESET: call active");
#endif
      FKT_TerminalResponse (p->response, (USHORT)resp_len);
    }
    else
    {
      #ifndef TI_PS_UICC_CHIPSET_15
	  T_SIM_CARD sim_info;
      #endif   /*  TI_PS_UICC_CHIPSET_15 */
      USHORT retcode;

      TRACE_ASSERT (cmd_ptr->sig_ptr);
      PFREE (cmd_ptr->sig_ptr);
      TRACE_ASSERT (p);
      MFREE (p);
      sim_data.remove_error = SIM_NO_ERROR;
      app_sim_remove ();
      sim_data.remove_error = SIM_CAUSE_CARD_REMOVED;

      #ifndef TI_PS_UICC_CHIPSET_15
         SIM_PowerOff ();
      #else
         simdrv_poweroff(readerId);
      #endif
      /* Force file selection */
      sim_data.act_directory = NOT_PRESENT_16BIT;
      sim_data.act_field     = NOT_PRESENT_16BIT;

      /*retcode = SIM_Restart (&sim_info); Driver does not call 'insert()'! */
      #ifndef TI_PS_UICC_CHIPSET_15
         retcode = SIM_Reset (&sim_info);
      #else
         retcode = simdrv_reset (readerId,voltageSelect);
      #endif
      TRACE_EVENT_P1 ("Result SIM Restart = %d", (int)retcode);
      TRACE_FUNCTION ("process_sim_refresh() exited(1)");
      return(1); //return and exit stk_proactive_polling(), if that is where called from
    }
    break;

  default:
    /*
     * not supported information request
     */
     TRACE_FUNCTION ("process_sim_refresh() default:");
     cmd_ptr->res_code[0] = STK_RES_ERR_CMD_TYPE;
     resp_len = stk_build_response (p->response, cmd_ptr->p_cmd, cmd_ptr->cmd_len,
                                    cmd_ptr->res_code, 1, NULL, 0);
#ifdef _SIMULATION_
     TRACE_EVENT("RFR: unknown qualifier");
#endif
     FKT_TerminalResponse (p->response, (USHORT)resp_len);
     break;
   }

   TRACE_ASSERT (cmd_ptr->sig_ptr);
   PFREE (cmd_ptr->sig_ptr);
   TRACE_ASSERT (p);
   MFREE (p);
   TRACE_FUNCTION ("process_sim_refresh() exited(0)");
   return(0);
          
}




GLOBAL void stk_proactive_polling (void)
{
  UBYTE *stk, *p_tag, *p_cmd = NULL;
  UBYTE *found_tag[STK_MAX_EXP_TAG];
  UBYTE compreh = 0, cmd_nr = 0, cmd_type, cmd_qual = 0;
  SHORT ber_len, tag_len, cmd_len, fl_len = 0, resp_len = 0;
  SHORT i, tag_i, cmd_i, tlv_len;
  const T_SAT_TAG_DESC *p_tag_desc;
  int offset;
  T_LOC_INFO loc_info;
  T_TIM_ADV tim_adv;

  TRACE_FUNCTION ("stk_proactive_polling()");

  if (SIM_IS_FLAG_SET (PRO_ACTIVE_SIM))
  {
    while (sim_data.proactive_sim_data_len > 0)
    {
      UINT   in_queue, out_queue;
      UBYTE  result = FALSE;
      UBYTE  res_code[2] = {STK_RES_SUCCESS, 0};
      T_TIME tm_val;
      T_STK_POLL_DATA *p;

      PALLOC (sim_toolkit_ind, SIM_TOOLKIT_IND);
      MALLOC (p, sizeof (T_STK_POLL_DATA));
      /*
       * clear indication primitive
       */
      memset (sim_toolkit_ind, 0, sizeof (T_SIM_TOOLKIT_IND));
      sim_toolkit_ind->stk_cmd.l_cmd = ((USHORT)sim_data.proactive_sim_data_len) << 3;
      ber_len = (SHORT)sim_data.proactive_sim_data_len;
      sim_data.proactive_sim_data_len = 0;
      sim_data.term_resp_sent         = FALSE;

      if (FKT_Fetch(sim_toolkit_ind->stk_cmd.cmd, ber_len) EQ SIM_NO_ERROR)
      {
        UBYTE tag;
        BOOL tag_not_found = TRUE;

#ifdef _SIMULATION_
        TRACE_EVENT("FKT_Fetch_EQ_SIM_NO_ERROR"); /* for debug purpose only */
#endif
        sim_data.ext_sat_cmd = FALSE;             /* internal command by default */

        stk = sim_toolkit_ind->stk_cmd.cmd;
        memset (found_tag, 0, sizeof(found_tag));
        tag_i = cmd_i = 0;
        cmd_len = 0;
        cmd_type = 0;

        tag = stk_process_tl(&stk, &ber_len, &tlv_len); /* BER tag */
        if (tag NEQ STK_PROACTIVE_SIM_COMMAND_TAG)
        {
          res_code[0] = STK_RES_ERR_MISS_VALUE;
        }
        else if (ber_len >= tlv_len)
        {
          ber_len = tlv_len;        // omit data after BER-TLV
          result = TRUE;
        }
        else /* ber_len < tlv_len */
        {
          if (tlv_len > 2)
          {
            res_code[0] = STK_RES_ERR_MISS_VALUE;
            result = TRUE;
          }
          else
          {
            res_code[0] = STK_RES_ERR_CMD_DATA;
          }
        }

        while (result AND ber_len > 0) // tag and length needed
        {
          UBYTE tag_simple;

          p_tag = stk;              // begin of TLV
          tag_len = ber_len;
          tag_simple = stk_process_tl(&stk, &ber_len, &tlv_len);

          if (ber_len < tlv_len)    // inconsistent length
          {
            if (res_code[0] NEQ STK_RES_ERR_MISS_VALUE)
            {
              TRACE_EVENT("ber_len < tlv_len -> STK_RES_ERR_CMD_DATA");
              res_code[0] = STK_RES_ERR_CMD_DATA;
            }
            result = FALSE;
            break;
          }
          else
            ber_len -= tlv_len;     // remaining BER-TLV

          tag_len -= ber_len;       // length of TLV

          if (tag EQ (tag_simple & ~STK_COMPREHENSION_REQUIRED))
          {
#ifdef _SIMULATION_
            TRACE_EVENT("TC_505A, TC_505B, TC_505C");
#endif
            stk += tlv_len;
            continue;
          }
          else
          {
            tag = tag_simple;
            tag_not_found = FALSE;
          }

          compreh = tag & STK_COMPREHENSION_REQUIRED;
          tag &= ~STK_COMPREHENSION_REQUIRED;

          do
          {
            p_tag_desc = &sat_cmd_list[cmd_i].tag_desc[tag_i];
            if (tag EQ p_tag_desc->tag)
            {
              break; /* tag found !!! */
            }
            else if (!p_tag_desc->mand)
            {
              tag_i++; /* skip non-mandatory tags */
            }
            else /* mandatory tag missed */
            {
              i = tag_i;
              res_code[0] = STK_RES_ERR_MISS_VALUE;
              while (i < (int)sat_cmd_list[cmd_i].max_tag)
              {
                p_tag_desc = &sat_cmd_list[cmd_i].tag_desc[i++];
                if (tag EQ p_tag_desc->tag AND !p_tag_desc->mand)
                {
#ifdef _SIMULATION_
                  TRACE_EVENT("TC_506");
#endif
                  res_code[0] = STK_RES_ERR_CMD_DATA;
                  break;
                }
              }
              if (!compreh AND i EQ (int)sat_cmd_list[cmd_i].max_tag)
              {
#ifdef _SIMULATION_
                TRACE_EVENT("TC_507");
#endif
                res_code[0] = STK_RES_SUCC_PART_COMPR;
                tag_not_found = TRUE;
              }
              break;
            }
          } while (tag_i < (int)sat_cmd_list[cmd_i].max_tag OR res_code[0]);

          if (tag_i >= (int)sat_cmd_list[cmd_i].max_tag)
          {
            i = (int)sat_cmd_list[cmd_i].tp_i;

            if ((~sat_tp_sim_ability[i] & sat_cmd_list[cmd_i].tp_flag) EQ 0)
            {
              break; /* the commmand is being handled outside the SIM */
            }

            if (compreh)
            {
#ifdef _SIMULATION_
              TRACE_EVENT("TC_502C, TC_504");
#endif
              res_code[0] = STK_RES_ERR_CMD_DATA;
              result = FALSE;
              break;
            }
          }
          else
          {
            p_tag_desc = &sat_cmd_list[cmd_i].tag_desc[tag_i];
            if (tag NEQ p_tag_desc->tag OR tlv_len < p_tag_desc->min_len)
            {
              if (compreh)
              {
#ifdef _SIMULATION_
                TRACE_EVENT("TC_503, TC_506");
#endif
                result = FALSE;
                break;
              }
            }
            else
              found_tag[tag_i] = stk;   // points to parameters of tag
          }

          if (tag_not_found)
          {
            stk += tlv_len;
            continue;
          }

          switch (tag)
          {
          case STK_COMMAND_DETAILS_TAG:
            p_cmd = p_tag;              // for TERMINAL RESPONSE
            cmd_len = tag_len;
            cmd_nr = stk[0];
            cmd_type = stk[1];
            cmd_qual = stk[2];

            TRACE_FUNCTION_P2("COMMAND_DETAILS: type=0x%02X, qlf=0x%02X",
                              (int)cmd_type, (int) cmd_qual);

            SIM_EM_PROACTIVE_COMMAND;

            for (i = 1; i < (SHORT)item_of(sat_cmd_list); i++) /* find out if known command */
            {
              if (cmd_type EQ sat_cmd_list[i].cmd_type)
              {
                cmd_i = i;
                break;
              }
            }
            if (i EQ item_of(sat_cmd_list))
            {
              TRACE_EVENT_P1("UNKNOWN COMMAND TYPE:0x%02X", cmd_type);
            }
            break;

          case STK_DEVICE_IDENTITY_TAG:
#ifdef _SIMULATION_
            TRACE_EVENT("found SIMPLE_TAG: STK_DEVICE_IDENTITY_TAG");
#endif
            break;

          case STK_CHANNEL_DATA_TAG:
#ifdef _SIMULATION_
            TRACE_EVENT("found SIMPLE_TAG: STK_CHANNEL_DATA_TAG");
#endif
            break;

          case STK_CHANNEL_DATA_LGTH_TAG:
#ifdef _SIMULATION_
            TRACE_EVENT("found SIMPLE_TAG: STK_CHANNEL_DATA_LGTH_TAG");
#endif
            break;

          case STK_FILE_LIST_TAG:
            fl_len = tlv_len;
            break;

          default:
#ifdef _SIMULATION_
            TRACE_EVENT_P1("other tag=0x%02X", tag);
#endif
            break;
          }
          if (++tag_i >= STK_MAX_EXP_TAG) /* incremented index points to next tag_desc entry */
            break;

          stk += tlv_len;
        }

        if (!result)
        {
          if (found_tag[0] EQ 0)
          {
            switch (res_code[0])
            {
            case STK_RES_ERR_MISS_VALUE:
#ifdef _SIMULATION_
              TRACE_EVENT("TC_501, TC_508");
#endif
              memcpy (p->response, &terminal_response_def, SAT_TRSP_MIN_RES);
              ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_nr = cmd_nr;
              ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_type = cmd_type;
              ((T_SIM_TRSP_SIMPLE *)p->response)->res_gnrl = res_code[0];
              FKT_TerminalResponse (p->response, SAT_TRSP_MIN_RES);
              break;

            default:
              break;
            }
          }
          else if (found_tag[0] AND cmd_i NEQ 0)
          {
            switch (res_code[0])
            {
            case STK_RES_ERR_CMD_DATA:
#ifdef _SIMULATION_
              TRACE_EVENT("TC_502A, TC_502B, TC_502C, TC_506");
#endif
              memcpy (p->response, &terminal_response_def, SAT_TRSP_MIN_RES);
              ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_nr = cmd_nr;
              ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_type = cmd_type;
              ((T_SIM_TRSP_SIMPLE *)p->response)->res_gnrl = res_code[0];
              FKT_TerminalResponse (p->response, SAT_TRSP_MIN_RES);
              break;

            case STK_RES_ERR_MISS_VALUE:
#ifdef _SIMULATION_
              TRACE_EVENT("TC_503, TC_509A");
#endif
              memcpy (p->response, &terminal_response_def, SAT_TRSP_MIN_RES);
              ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_nr = cmd_nr;
              ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_type = cmd_type;
              ((T_SIM_TRSP_SIMPLE *)p->response)->res_gnrl = res_code[0];
              FKT_TerminalResponse (p->response, SAT_TRSP_MIN_RES);
              break;

            default:
              break;
            }
          }
          else if (cmd_i EQ 0)
          {
#ifdef _SIMULATION_
            TRACE_EVENT("TC_504");
#endif
            res_code[0] = STK_RES_ERR_CMD_TYPE;
            memcpy (p->response, &terminal_response_def, SAT_TRSP_MIN_RES);
            ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_nr = cmd_nr;
            ((T_SIM_TRSP_SIMPLE *)p->response)->cmd_type = cmd_type;
            ((T_SIM_TRSP_SIMPLE *)p->response)->res_gnrl = res_code[0];
            FKT_TerminalResponse (p->response, SAT_TRSP_MIN_RES);
          }
          else
          {
            resp_len = stk_build_response (p->response, p_cmd, cmd_len, res_code, 1, NULL, 0);
#ifdef _SIMULATION_
            TRACE_EVENT("SAT: other error");
#endif
            FKT_TerminalResponse (p->response, (USHORT)resp_len);
          }
          PFREE (sim_toolkit_ind);
        }
        else switch (cmd_type)
        {
          case STK_DISPLAY_TEXT:
          case STK_GET_INKEY:
          case STK_GET_INPUT:
          case STK_PLAY_TONE:
          case STK_SET_UP_MENU:
          case STK_SELECT_ITEM:
          case STK_SEND_SMS:
          case STK_SEND_SS:
          case STK_SET_UP_CALL:

          case STK_SETUP_EVENT_LIST:
          case STK_SEND_USSD:
          case STK_SEND_DTMF:
          case STK_SETUP_IDLE_TEXT:
          case STK_LAUNCH_BROWSER:
          case STK_RUN_AT_CMD:
          case STK_LANGUAGE_NOTIFICATION:
#ifdef FF_SAT_E
          case STK_OPEN_CHANNEL:
          case STK_CLOSE_CHANNEL:
          case STK_GET_CHANNEL_STAT:
#endif /* FF_SAT_E */
            /*
             * Operations processed by MMI / MFW
             */
            sim_data.sat_session = TRUE;
            sim_data.ext_sat_cmd = TRUE;
            PSENDX (MMI, sim_toolkit_ind);
            break;

          case STK_POLL_INTERVALL:
            /*
             * SIM toolkit defines an idle poll interval. The timer in
             * SIM application is stopped and started with the
             * new value. A terminal response with the used time
             * is sent to SIM toolkit.
             */
            if (found_tag[2] NEQ NULL)
            {
              BOOL org_val;
              TRACE_EVENT("Idle Polling switched on");

              if (found_tag[2][1] NEQ 0) /* value not "reserved" */
              {
                switch (found_tag[2][0])
                {
                case 0: /* minutes */
                  if ((ULONG)found_tag[2][1] * 600L >= (ULONG)cusSatMinPollItv)
                  {
                    sim_data.status_time = ((T_TIME)found_tag[2][1]) * 60L * 1000
                                            - TIMER_LATENCY;
                    org_val = TRUE;
                  }
                  else
                    org_val = FALSE;
                  break;
                case 1: /* seconds */
                  if ((USHORT)found_tag[2][1] * 10 >= cusSatMinPollItv)
                  {
                    sim_data.status_time = ((T_TIME)found_tag[2][1]) * 1000L
                                            - TIMER_LATENCY;
                    org_val = TRUE;
                  }
                  else
                    org_val = FALSE;
                  break;
                case 2: /* tenth seconds */
                  if ((USHORT)found_tag[2][1] >= cusSatMinPollItv)
                  {
                    sim_data.status_time = ((T_TIME)found_tag[2][1]) * 100L
                                            - TIMER_LATENCY;
                    org_val = TRUE;
                  }
                  else
                    org_val = FALSE;
                  break;
                default: /* command data not understood */
                  res_code[0] = STK_RES_ERR_CMD_DATA;
                  org_val = TRUE;
                  break; /* return original values */
                }
              }
              else /* return original values */
              {
                res_code[0] = STK_RES_ERR_CMD_DATA;
                org_val = TRUE;
              }

              resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                             res_code, 1, (UBYTE *)tag_dur, sizeof(tag_dur));
#ifdef _SIMULATION_
              TRACE_EVENT("POLL_ITV data not understood");
#endif
              if (org_val)
              {
                p->response[cmd_len+ 9] = found_tag[2][0];  /* copy unit            */
                /* copy number of units (1 to 255) or 0 !!! */
                p->response[cmd_len+10] = found_tag[2][1];
              }
              else
              {
                sim_data.status_time = ((T_TIME)cusSatMinPollItv) * 100L
                                        - TIMER_LATENCY;
                if (cusSatMinPollItv < 0x100)
                {
                  p->response[cmd_len+ 9] = 2;     // fits to tenth of seconds
                  p->response[cmd_len+10] = (UBYTE)cusSatMinPollItv;
                }
                else if (cusSatMinPollItv < (0x100*10))
                {
                  p->response[cmd_len+ 9] = 1;     // fits to seconds
                  p->response[cmd_len+10] = (UBYTE)((cusSatMinPollItv / 5 + 1) / 2);
                }
                else
                {
                  p->response[cmd_len+ 9] = 0;     // fits to minutes
                  p->response[cmd_len+10] = (UBYTE)((cusSatMinPollItv / 300 + 1) / 2);
                }
              }
            sim_data.idle_polling = TRUE;
            }
            else
            {
              res_code[0] = STK_RES_ERR_MISS_VALUE;
              resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                             res_code, 1, NULL, 0);
#ifdef _SIMULATION_
              TRACE_EVENT("POLL_ITV missing value");
#endif
            }
            FKT_TerminalResponse (p->response, (USHORT)resp_len);
            PFREE (sim_toolkit_ind);

            if (SIM_IS_FLAG_CLEARED (CALL_ACTIVE) OR
                sim_data.status_time < THIRTY_SECONDS)
              TIMER_PSTART( sim_handle,
                            SIM_TIMER,
                            sim_data.status_time,
                            sim_data.status_time);
            break;

          case STK_PROVIDE_LOCAL_INFO:
            /*
             * SIM toolkit request local information from the
             * SIM application. These informations are:
             * MCC, MNC, LAC, Cell Identity or IMEI.
             * SIM application sends this information with
             * a terminal response to the SIM toolkit.
             */
            if(p_cmd EQ NULL) 
            {
               TRACE_EVENT("p_cmd is NULL");
               return;
            }
            switch (cmd_qual)
            {
              case QLF_PLOI_LOC_INFO:
                /*
                 * request location information
                 */
#ifdef _SIMULATION_
                if (sim_data.location_info.c_loc NEQ 0)
                {
                  memcpy (p->response, p_cmd, cmd_len);
                  /* location information available */
                  memcpy (&p->response[cmd_len], &terminal_response_loci[5], 9);
                  /* copy MCC, MNC & LAC */
                  memcpy (&p->response[cmd_len+ 9], &sim_data.location_info.loc[4], 5);
                  /* copy cell identity */
                  p->response[cmd_len+14] = sim_data.cell_identity >> 8;
                  p->response[cmd_len+15] = sim_data.cell_identity & 0xFF;
                  p->response[cmd_len+ 6] = res_code[0];
                  resp_len = cmd_len + 16;
#else
                if((cl_shrd_get_loc (&loc_info) EQ TRUE) AND
                   (loc_info.service_mode NEQ NO_SERVICE))
                {
                  memcpy (p->response, p_cmd, cmd_len);
                  /* location information available */
                  memcpy (&p->response[cmd_len], &terminal_response_loci[5], 9);
                  /* copy from loc_info to response */
                  p->response[cmd_len+9]   = loc_info.mcc[1] << 4;
                  p->response[cmd_len+9]  += loc_info.mcc[0];
                  p->response[cmd_len+10]  = loc_info.mnc[2] << 4;
                  p->response[cmd_len+10] += loc_info.mcc[2];
                  p->response[cmd_len+11]  = loc_info.mnc[1] << 4;
                  p->response[cmd_len+11] += loc_info.mnc[0];
                  p->response[cmd_len+12]  = loc_info.lac >> 8;
                  p->response[cmd_len+13]  = loc_info.lac & 0xff;
                  p->response[cmd_len+14]  = loc_info.cell_id >> 8;
                  p->response[cmd_len+15]  = loc_info.cell_id & 0xFF;
                  
                  if ( loc_info.service_mode EQ LIMITED_SERVICE )
                  {
                    p->response[cmd_len+ 6] = STK_RES_SUCC_LIMITED_SERVICE;
                  }
                  else
                  {
                    p->response[cmd_len+ 6] = res_code[0];
                  }
                  resp_len = cmd_len + 16;
#endif  /* _SIMULATION_ */
                }
                else
                {
                  /* location information not available */
                  res_code[0] = STK_RES_BUSY_ME;
                  res_code[1] = STK_RES_EXT_NO_SERVICE;
                  resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                                 res_code, 2, NULL, 0);
#ifdef _SIMULATION_
                  TRACE_EVENT("PLI: local info not available");
#endif
                }
                sim_data.ext_sat_cmd = FALSE;
                break;
              case QLF_PLOI_IMEI:
                /*
                 * request IMEI
                 */
                memcpy (p->response, p_cmd, cmd_len);
                memcpy (&p->response[cmd_len], &terminal_response_imei[5], 17);

                cl_get_imeisv(CL_IMEI_SIZE,
                              &p->response[cmd_len + 9],
                              CL_IMEI_GET_STORED_IMEI);
                for (i = (int)cmd_len + 8 + CL_IMEI_SIZE;
                     i > (int)cmd_len + 9; i--)
                {     /* place nibbles according to 4.08 */
                  p->response[i] = (p->response[i] & 0xf0) |
                                   (p->response[i - 1] &  0x0f);
                }
                /* i points to first IMEI octet, set 'type of identity' */
                p->response[i] = (p->response[i] & 0xf0) | 0xA;
                p->response[cmd_len+8+CL_IMEI_SIZE] &= 0xF;
                p->response[cmd_len+ 6] = res_code[0];
                resp_len = cmd_len + 17;
                sim_data.ext_sat_cmd = FALSE;
                break;
              case QLF_PLOI_NTW_MSR:
                /*
                 * request network measurement results and BCCH list
                 */
                if ((sat_tp_sim_enabled[3] & SAT_TP4_PLI_NMR) EQ 0)
                {
                  /* if not effective */
                  res_code[0] = STK_RES_ERR_NO_SUPPORT;
                  resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                                 res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                  TRACE_EVENT("PLI: NMR not supported");
#endif
                  break;
                }
                memcpy (p->response, p_cmd, cmd_len);
                /* location information available */
                memcpy (&p->response[cmd_len], &terminal_response_nmr[5], 9);
                if (get_network_meas (&p->response[cmd_len+9]))
                {
                  /*
                   * set result code
                   */
#ifdef _SIMULATION_
                  p->response[cmd_len+ 6] = res_code[0];
                  resp_len = cmd_len + 25;
#else
                  if ((cl_shrd_get_loc (&loc_info) EQ TRUE) AND
                      (loc_info.service_mode NEQ NO_SERVICE))
                  {
                    if ( loc_info.service_mode EQ LIMITED_SERVICE )
                    {
                      p->response[cmd_len+ 6] = STK_RES_SUCC_LIMITED_SERVICE;
                    }
                    else
                    {
                      p->response[cmd_len+ 6] = res_code[0];
                    }
                    resp_len = cmd_len + 25;
                  }
                  else
                  {
                    res_code[0] = STK_RES_BUSY_ME;
                    res_code[1] = STK_RES_EXT_NO_SERVICE;
                    resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                                  res_code, 2, NULL, 0);
#ifdef _SIMULATION_
                   TRACE_EVENT("PLI: service mode not available");
#endif /* _SIMULATION_ */
                  }
#endif /* _SIMULATION_ */
                  /*
                   * Add BCCH list
                   */
                  if (get_bcch_chan_list (&p->stk_data))
                  {
                    /*
                     * copy BCCH data list for answer
                     */
                    p->response[resp_len] = 0x1D;  /* BCCH channel flag */
                    p->response[resp_len + 1] = p->stk_data.stk_length;
                    memcpy (&p->response[resp_len + 2], p->stk_data.stk_parameter,
                            p->stk_data.stk_length);
                    resp_len += (2+p->stk_data.stk_length);
                  }
                  else
                  {
                    /* location information not available */
                    res_code[0] = STK_RES_BUSY_ME;
                    res_code[1] = STK_RES_EXT_NO_SERVICE;
                    resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                                   res_code, 2, NULL, 0);
#ifdef _SIMULATION_
                    TRACE_EVENT("PLI: BCCH list not available");
#endif
                  }
                }
                else
                {
                  /* location information not available */
                  res_code[0] = STK_RES_BUSY_ME;
                  res_code[1] = STK_RES_EXT_NO_SERVICE;
                  resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                                 res_code, 2, NULL, 0);
#ifdef _SIMULATION_
                  TRACE_EVENT("PLI: measurement not available");
#endif
                }
                sim_data.ext_sat_cmd = FALSE;
                break;
              case QLF_PLOI_DTT:
                /*
                 * Date, Time and Timezone
                 */
                if ((sim_data.stk_profile[7] & SAT_TP8_PLI_DTT) EQ 0)
                {
                  /* if not effective */
                  res_code[0] = STK_RES_ERR_NO_SUPPORT;
                  resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                                 res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                  TRACE_EVENT("PLI: not supported in TP");
#endif
                  break;
                }
                /*
                 * Operations processed by MMI / MFW
                 */
                sim_data.ext_sat_cmd = TRUE;
                PSENDX (MMI, sim_toolkit_ind);
                break;
              case QLF_PLOI_LANG_SET:
               /*
                * Language Setting to be supported (to be processed by ACI)
                */
                if ((sim_data.stk_profile[8] & SAT_TP9_PLI_LANG) EQ 0)
                {
                  /* if not effective */
                  res_code[0] = STK_RES_ERR_NO_SUPPORT;
                  resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                                 res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                  TRACE_EVENT("language setting not supported");
#endif
                  break;
                }
                /*
                 * To be processed by ACI
                 */
                sim_data.sat_session = TRUE;
                sim_data.ext_sat_cmd = TRUE;
                PSENDX (MMI, sim_toolkit_ind);
                break;

              case QLF_PLOI_TIM_ADV:
                
                if ((sat_tp_sim_enabled[8] & SAT_TP9_PLI_TIMING_ADV) EQ 0)
                {
                  res_code[0] = STK_RES_ERR_NO_SUPPORT;
                  resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                               res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                  TRACE_EVENT("PLI: timing advance not supported");
#endif
                }
                else
                {
                  memset (&tim_adv, 0, sizeof(T_TIM_ADV));
                  memcpy (p->response, p_cmd, cmd_len);
                  memcpy (&p->response[cmd_len], &terminal_response_timingadv[5], 11);
#ifdef _SIMULATION_
                  p->response[cmd_len+ 6] = res_code[0];
                  resp_len = cmd_len + 11;
#else
                 if(cl_shrd_get_tim_adv (&tim_adv) EQ TRUE)
                 {


                   p->response[cmd_len+9] = tim_adv.me_status;
                   p->response[cmd_len+10] = tim_adv.tm_adv;
                   /*
                   * Set result code.
                   */
                   p->response[cmd_len+ 6] = res_code[0];
                   resp_len = cmd_len + 11;
                 }
                 else
                 {
                    res_code[0] = STK_RES_BUSY_ME;
                    resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                               res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                  TRACE_EVENT("PLI: Timing Advance not available");
#endif
                 }
#endif /* _SIMULATION_ */
                }

                sim_data.ext_sat_cmd = FALSE;
                break;
              default:
                /*
                 * no valid command qualifier
                 */
                res_code[0] = STK_RES_ERR_CMD_TYPE;
                resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                               res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                TRACE_EVENT("PLI: type not understood");
#endif
                sim_data.ext_sat_cmd = FALSE;
                break;
            }
            if (!sim_data.ext_sat_cmd)   /* may depend on Command Qualifier */
            {
              FKT_TerminalResponse (p->response, (USHORT)resp_len);
              PFREE (sim_toolkit_ind);
            }
            break;

          case STK_REFRESH:
            /*
             * process SIM REFRESH according to command qualifier
             */
            TRACE_EVENT("process SIM REFRESH according to command qualifier");

            /* MALLOC area for CONTEXT SWITCH */
            if ( sim_data.context_switch_ptr != NULL )
            {
              TRACE_EVENT("ERROR!! context_switch_ptr should be NULL - freeing");
              MFREE ( sim_data.context_switch_ptr );
              sim_data.context_switch_ptr = NULL;
            }
            MALLOC (sim_data.context_switch_ptr, sizeof (T_CONTEXT_SWITCH));
            memset ( sim_data.context_switch_ptr,0, sizeof (T_CONTEXT_SWITCH));

            /* Set sig_ptr to handle required signal */
#ifdef TI_PS_FF_AT_P_CMD_CUST
            if (sim_data.cust_mode EQ 1)
            {
              /* Cust_Mode 1 operation setup*/
              PALLOC(copy_sim_toolkit_ind,SIM_TOOLKIT_IND);
              memcpy(copy_sim_toolkit_ind,sim_toolkit_ind,sizeof(T_SIM_TOOLKIT_IND));
              sim_data.context_switch_ptr->sig_ptr = copy_sim_toolkit_ind;
            }
            else
            {
              /*default operation setup*/
              sim_data.context_switch_ptr->sig_ptr = sim_toolkit_ind;
            }
#else
            /*default operation setup*/
            sim_data.context_switch_ptr->sig_ptr = sim_toolkit_ind;
#endif /* TI_PS_FF_AT_P_CMD_CUST */

            /* Save decoding of original sim_toolkit_ind  signal processed by stk_proactive_polling */
            offset = (long)found_tag[2] - (long)sim_toolkit_ind;
            sim_data.context_switch_ptr->tag2 = (UBYTE *)(sim_data.context_switch_ptr->sig_ptr) + offset;
            sim_data.context_switch_ptr->fl_len = fl_len;
            offset = (long)p_cmd - (long)sim_toolkit_ind;
            sim_data.context_switch_ptr->p_cmd = (UBYTE *)(sim_data.context_switch_ptr->sig_ptr) + offset;
            sim_data.context_switch_ptr->cmd_len = cmd_len;
            sim_data.context_switch_ptr->res_code[0]=res_code[0];
            sim_data.context_switch_ptr->res_code[1]=res_code[1];

#ifdef TI_PS_FF_AT_P_CMD_CUST
            /* functionality is depended on cust_mode */
            if (sim_data.cust_mode EQ 1)
            {
              /* Cust_Mode 1 operation */
              sim_data.user_confirmation_expected = TRUE;

              /*send Refresh command to MMI*/
              PSENDX (MMI, sim_toolkit_ind);

              /*REFRESH COMMAND NOW PROCESSED IN stk_sim_refresh_user_res()      */
              /*note: stk_sim_refresh_user_res() will call process_sim_refresh() */
              /*      This routine will free sig_ptr, user must free the         */
              /*      context_switch.                                            */

              /*Terminate Command */
              break; 
            }

            else 
            {
              /* sim_data.cust_mode EQ 0 */
              /* process default operation */
              if ( process_sim_refresh(sim_data.context_switch_ptr) )
              {
                /* processed a SIM_RESET. Special case - exit stk_proactive_polling()*/
                MFREE(p);
                /* this thread has finished with the context switch so free it.      */
                MFREE (sim_data.context_switch_ptr);
                sim_data.context_switch_ptr = NULL;
                return;   /* exit from stk_proactive_polling() */
              }
              else
              {
                /* process_sim_refresh() frees signal  sim_data.context_switch_ptr->sig_ptr */
                /* this thread has finished with the context switch so free it.             */
                MFREE (sim_data.context_switch_ptr); 
                sim_data.context_switch_ptr = NULL;
              }
            }
#else
            /* sim_data.cust_mode EQ 0 */
            /* process default operation */
            if ( process_sim_refresh(sim_data.context_switch_ptr) )
            {
              /* processed a SIM_RESET. Special case - exit stk_proactive_polling()*/
              MFREE(p);
              /* this thread has finished with the context switch so free it.      */
              MFREE (sim_data.context_switch_ptr);
              sim_data.context_switch_ptr = NULL;
              return;   /* exit from stk_proactive_polling() */
            }
            else
            {
              /* process_sim_refresh() frees signal  sim_data.context_switch_ptr->sig_ptr */
              /* this thread has finished with the context switch so free it.             */
              MFREE (sim_data.context_switch_ptr); 
              sim_data.context_switch_ptr = NULL;
            }
#endif /* TI_PS_FF_AT_P_CMD_CUST */
            break; //end of case STK_REFRESH

#ifdef FF_SAT_E
          case STK_RECEIVE_DATA:
            if (stk_dti_bip_receive_data((T_sdu*)&sim_toolkit_ind->stk_cmd, res_code[0]))
            {
              /*
               * message contains TLV elements to display
               * so forward it to MMI
               */
              sim_data.sat_session = TRUE;

              TRACE_EVENT("SEND receive data indication to MMI");
              PSENDX (MMI, sim_toolkit_ind);
              TRACE_EVENT("receive data indication to MMI sent");
            }
            else
            {
              PFREE (sim_toolkit_ind);
            }
            break;

          case STK_SEND_DATA:
            if (stk_dti_bip_send_data((T_sdu*)&sim_toolkit_ind->stk_cmd))
            {
              /*
               * message contains TLV elements to display
               * so forward it to MMI
               */
              sim_data.sat_session = TRUE;
              PSENDX (MMI, sim_toolkit_ind);
            }
            else
            {
              PFREE (sim_toolkit_ind);
            }
          break;
#endif /* FF_SAT_E */

          case STK_TIMER_MANAGEMENT:
          {
            UBYTE tag_tv[8] = {STK_TIMER_ID_TAG|STK_COMPREHENSION_REQUIRED, STK_TIMER_ID_LEN, 0,
                               STK_TIMER_VALUE_TAG, STK_TIMER_VALUE_LEN,
                               0, 0 ,0};
            tag_tv[2] = found_tag[2][0];

            if ((unsigned)(i = (int)found_tag[2][0] - 1) >= MAX_SAT_TIMER)
            {               /* invalid Timer identifier */
              res_code[0] = STK_RES_ERR_CMD_DATA;
              resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                             res_code, 1, NULL, 0);
#ifdef _SIMULATION_
              TRACE_EVENT("stk_build_response No 17");
#endif
            }
            /*
             * Process TIMER MANAGEMENT according to command qualifier
             */
            else switch (cmd_qual)
            {
            case 0:
              if (found_tag[3] EQ NULL)
              {
                res_code[0] = STK_RES_ERR_MISS_VALUE;
                resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                               res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                TRACE_EVENT("TM: missing parameters");
#endif
                break;
              }
              /* translate timer value into unit of seconds */
              tm_val = ((T_TIME)BCD2INT(found_tag[3][0])  * 60 + // hours
                        (T_TIME)BCD2INT(found_tag[3][1])) * 60 + // minutes
                        (T_TIME)BCD2INT(found_tag[3][2]);        // seconds
//TISH, patch for OMAPS00115011, 2007-02-12
//start
		if (tm_val==0)
		{
                res_code[0] = STK_RES_ERR_CMD_DATA;
                resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                               res_code, 1, NULL, 0);
		  TRACE_ERROR("TR wrong tm value");
                break;
		}
//end
              sim_data.timer[i].hour = found_tag[3][0];
              sim_data.timer[i].minute = found_tag[3][1];
              sim_data.timer[i].second = found_tag[3][2];

              TIMER_START (sim_handle, (USHORT)(i+1), (tm_val * 1000 - TIMER_LATENCY));
              sim_data.timer[i].active = TRUE;
              resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                             res_code, 1, tag_tv, 3);
#ifdef _SIMULATION_
              TRACE_EVENT("TM: set timer");
#endif
              break;
            case 1:
            case 2:
              if (sim_data.timer[i].active)
              {
                TIMER_STATUS (sim_handle, (USHORT)(i + 1), &tm_val);
                tm_val /= 1000;
                tag_tv[7] = INT2BCD((UBYTE)(tm_val % 60));
                tm_val /= 60;
                tag_tv[6] = INT2BCD((UBYTE)(tm_val % 60));
                tm_val /= 60;
                if (tm_val < 24)
                  tag_tv[5] = INT2BCD((UBYTE)tm_val);
                else
                {             // set maximum value
                  tag_tv[7] = tag_tv[6] = 0x59;
                  tag_tv[5] = 0x23;
                }
                if (cmd_qual EQ 1)  /* timer to be stopped */
                {
                  TIMER_STOP (sim_handle, (USHORT)(i + 1));
                  sim_data.timer[i].active = FALSE;
                }
                resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                               res_code, 1, tag_tv, 8);
#ifdef _SIMULATION_
                TRACE_EVENT("TM: stop/query timer");
#endif
              }
              else
              {
                res_code[0] = STK_RES_BUSY_TIMER_STATE;
                resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                               res_code, 1, NULL, 0);
#ifdef _SIMULATION_
                TRACE_EVENT("TM: timer not running");
#endif
              }
              break;
            default:
              /*
               * not supported information request
               */
              res_code[0] = STK_RES_ERR_CMD_TYPE;
              resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                             res_code, 1, NULL, 0);
#ifdef _SIMULATION_
              TRACE_EVENT("TM: unknown qualifier");
#endif
              break;
            }
            FKT_TerminalResponse (p->response, (USHORT)resp_len);
            PFREE (sim_toolkit_ind);
            break;
          }
          default:
            result = FALSE;
            res_code[0] = STK_RES_ERR_CMD_TYPE; /* command type not understood */
            /*
             * fall through
            */
          case STK_POLLING_OFF:
            /*
             * SIM toolkit cancels the effect of a previous
             * POLL INTERVAL command. Polling of the SIM
             * toolkit is done now all thirty seconds with the
             * STATUS command, when in a call.
             */
            if (result AND SIM_IS_FLAG_SET (PRO_ACTIVE_SIM))
            {
              TRACE_EVENT("Idle Polling switched off");
              sim_data.idle_polling = FALSE;
             /* there will not be a status command after this .so just force one status command to enable sleep */  
			  startTimerPollOff = TRUE; 
              if(SIM_IS_FLAG_SET(CALL_ACTIVE))
              {
               /* SIM_TIMER will be restarted, during a call, for
                * presence detection
                */
                sim_data.status_time  = THIRTY_SECONDS;
              }
              else
              {
                /* timer value set to max, for with a '0', the timer would
                   run for about one tick
                 */
                sim_data.status_time  = 0xFFFFFFFF;
                TIMER_STOP (sim_handle, SIM_TIMER);
              }

            }
          case STK_MORE_TIME:
            /*
             * SIM toolkit needs more time.
             * SIM application sends terminal response with OK.
             */
            resp_len = stk_build_response (p->response, p_cmd, cmd_len,
                                           res_code, 1, NULL, 0);
#ifdef _SIMULATION_
            TRACE_EVENT("MORE_TIME");
#endif
            FKT_TerminalResponse (p->response, (USHORT)resp_len);
            PFREE (sim_toolkit_ind);
            break;
        }
      }
      else
      {
#ifdef _SIMULATION_
        TRACE_EVENT("FKT_Fetch_NEQ_SIM_NO_ERROR");
#endif
        PFREE (sim_toolkit_ind);
      }
      MFREE (p);

      if (vsi_c_status (VSI_CALLER &in_queue, &out_queue) EQ VSI_OK)
      {
        if (in_queue > 0) break; /* break while */
      }      
    } /* END while */
    /*
     * send end of SAT session indicator
     */
    TRACE_FUNCTION ("stk_proactive_polling() send end of SAT session indicator");
    if ((sim_data.term_resp_sent) AND (sim_data.sat_session))
    {
      PALLOC (sim_toolkit_ind, SIM_TOOLKIT_IND);
      memset (sim_toolkit_ind, 0, sizeof (T_SIM_TOOLKIT_IND));
#ifdef _SIMULATION_
      TRACE_EVENT("SAT session ended");
#endif
      sim_data.sat_session    = FALSE;
      sim_data.term_resp_sent = FALSE;
      PSENDX (MMI, sim_toolkit_ind);
    }
  }
  TRACE_FUNCTION ("stk_proactive_polling() exited");
}




/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_stop_all_sat_timers    |
+--------------------------------------------------------------------+

  PURPOSE : Stop all timers started by TIMER MANAGEMENT, if running.
            Required when card is deactivated or reset.

*/

GLOBAL void stk_stop_all_sat_timers (void)
{
  int i;

  for (i = 0; i < MAX_SAT_TIMER; i++)
  {
    if (sim_data.timer[i].active)
    {
      TIMER_STOP (sim_handle, (USHORT)(i + 1));
      sim_data.timer[i].active = FALSE;
    }
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_start_timer_and_poll   |
+--------------------------------------------------------------------+

  PURPOSE : Start STATUS timer and control SIM Toolkit Polling

*/

LOCAL void stk_start_timer_and_poll (void)
{
  T_TIME t_val;
  /*
   * start status timer if SIM is inserted
   * for periodic status polling of SIM Toolkit
   */
  if ((SIM_IS_FLAG_SET (PRO_ACTIVE_SIM) AND
       sim_data.idle_polling AND
       SIM_IS_FLAG_CLEARED (TEST_MODE_POLLING)) OR
       SIM_IS_FLAG_SET (CALL_ACTIVE))
  {
  /*
   * Start Status Polling
   */
    t_val = (SIM_IS_FLAG_SET (CALL_ACTIVE) AND
             sim_data.status_time > THIRTY_SECONDS)?
            THIRTY_SECONDS: sim_data.status_time;

    TIMER_PSTART (sim_handle, SIM_TIMER, t_val, t_val);
  }
  sim_data.chk_sat_avail = TRUE;
//  stk_proactive_polling();
}

#ifdef FF_SAT_E
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_handle_ccd_error       |
+--------------------------------------------------------------------+

  PURPOSE : Handle CCD error causes.

*/

LOCAL void stk_handle_ccd_error(UBYTE notOK,
                                UBYTE* status,
                                UBYTE* general_result,
                                UBYTE* add_info_result)
{
  UBYTE  ccd_error;
  USHORT parameter_list[MAX_ERR_PAR];
  TRACE_EVENT_P1("stk_handle_ccd_error(): %d", notOK);
  /*
   * handle errors in list
   */
  memset (parameter_list, 0, sizeof(parameter_list));
  ccd_error = ccd_getFirstError(CCDENT_SAT, parameter_list);

  if (notOK EQ ccdWarning)
  {
    while (ccd_error NEQ ERR_NO_MORE_ERROR)
    {
      switch (ccd_error)
      {
      case ERR_COMPREH_REQUIRED:
        /*
         * comprehension required
         */
        TRACE_ERROR("CCD_WARNING=ERR_COMPREH_REQUIRED");
        if (*status EQ SIM_CCD_OK)
        {
          *general_result  = RSLT_UNKN_DATA;
          *add_info_result = ADD_NO_CAUSE;
          *status          = SIM_CCD_RETURN;
        }
        break;

      case ERR_IE_NOT_EXPECTED:
        /*
         * unexpected element
         */
        TRACE_ERROR("CCD_WARNING=ERR_IE_NOT_EXPECTED");
        if (*status EQ SIM_CCD_OK)
        {
          *general_result  = RSLT_PERF_PART_CMPR;
          *add_info_result = ADD_NO_CAUSE;
        }
        break;

      case ERR_MAND_ELEM_MISS:
        /*
         * mandatory elements missing
         */
        TRACE_ERROR("CCD_WARNING=ERR_MAND_ELEM_MISS");
        *general_result  = RSLT_ERR_REQ_VAL;
        *add_info_result = ADD_NO_CAUSE;
        *status          = SIM_CCD_RETURN;
        break;

      case ERR_MSG_LEN:
        TRACE_ERROR("CCD_WARNING=ERR_MSG_LEN (TC_509B)");
        *general_result  = RSLT_PERF_SUCCESS;
        *add_info_result = ADD_NO_CAUSE;
        *status          = SIM_CCD_OK;
        break;

      default:
        TRACE_ERROR("CCD_WARNING ignored");
        TRACE_EVENT_P1("ccd_error=0x%02X", ccd_error);
        break;
      }
      memset (parameter_list,0, sizeof(parameter_list));
      ccd_error = ccd_getNextError (CCDENT_SAT, parameter_list);
    }
  }
  else /* ccdError */
  {
    while (ccd_error NEQ ERR_NO_MORE_ERROR)
    {
      switch (ccd_error)
      {
      case ERR_COMPREH_REQUIRED:
        /*
         * comprehension required
         */
        TRACE_ERROR("CCD_ERROR=ERR_COMPREH_REQUIRED");
        if (*status EQ SIM_CCD_OK)
        {
          *general_result  = RSLT_UNKN_DATA;
          *add_info_result = ADD_NO_CAUSE;
          *status          = SIM_CCD_RETURN;
        }
        break;

      case ERR_IE_NOT_EXPECTED:
        /*
         * unexpected element
         */
        TRACE_ERROR("CCD_ERROR=ERR_IE_NOT_EXPECTED");
        if (*status EQ SIM_CCD_OK)
        {
          *general_result  = RSLT_PERF_PART_CMPR;
          *add_info_result = ADD_NO_CAUSE;
        }
        break;

      case ERR_MAND_ELEM_MISS:
        /*
         * mandatory elements missing
         */
        TRACE_ERROR("CCD_ERROR=ERR_MAND_ELEM_MISS");
        *general_result  = RSLT_ERR_REQ_VAL;
        *add_info_result = ADD_NO_CAUSE;
        *status          = SIM_CCD_RETURN;
        break;

      case ERR_MSG_LEN:
        TRACE_ERROR("CCD_ERROR=ERR_MSG_LEN");
        *general_result  = RSLT_UNKN_DATA;
        *add_info_result = ADD_NO_CAUSE;
        *status          = SIM_CCD_DISCARD;
        break;

      default:
        TRACE_ERROR("CCD_ERROR ignored");
        TRACE_EVENT_P1("ccd_error=0x%02X", ccd_error);
        break;
      }
      memset (parameter_list,0, sizeof(parameter_list));
      ccd_error = ccd_getNextError (CCDENT_SAT, parameter_list);
    }
  }
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_bip_decode_stk_command |
+--------------------------------------------------------------------+

  PURPOSE : First step of decoding SEND DATA and RECEIVE DATA message.

*/

LOCAL void stk_bip_decode_stk_command(T_sdu*          message,
                                      T_cmd_details*  cmd_details,
                                      UBYTE*          status,
                                      UBYTE*          general_result,
                                      UBYTE*          add_info_result)
{
  UBYTE ccdRet;
  MCAST(stk_cmd, STK_CMD);
  memset(stk_cmd, 0, sizeof(T_STK_CMD));
  /*
   * decode toolkit command
   */   
  ccdRet = ccd_decodeMsg (CCDENT_SAT,
                          DOWNLINK,
                          (T_MSGBUF *) message,
                          (UBYTE    *) _decodedMsg,
                          STK_CMD);

#ifdef _SIMULATION_
  TRACE_EVENT_P1("ccdRet@bip_decode_stk_command: %d", ccdRet);
#endif 

  if ((stk_cmd->v_pas_cmd) AND (stk_cmd->pas_cmd.v_cmd_details))
  {
    /*
     * store command details
     */
    *cmd_details = stk_cmd->pas_cmd.cmd_details;

    if (ccdRet NEQ ccdOK)
    {
      /*
       * handle errors in list
       */
      stk_handle_ccd_error(ccdRet, status, general_result, add_info_result);
    }
    if ((stk_cmd->pas_cmd.v_cmd_prms EQ FALSE) OR
       (stk_cmd->pas_cmd.v_dev_ids EQ FALSE))
    {
      /*
       * no Channel Data (Length) element present or
       * no Device Identities element present
       * Error, required values are missing
       */
      *general_result  = RSLT_ERR_REQ_VAL;
      *add_info_result = ADD_NO_CAUSE;
      *status          = SIM_CCD_RETURN;
    }
    if (*status EQ SIM_CCD_OK)
    {
      int i = 0;
      while (tbl_device_src_id[i])
      {
        if (stk_cmd->pas_cmd.dev_ids.dest_dev EQ tbl_device_src_id[i])
         break;

        i++;
      }
      if (tbl_device_src_id[i] EQ 0)
      {
        /*
         * device id not valid
         */
        *general_result  = RSLT_UNKN_DATA;
        *add_info_result = ADD_NO_CAUSE;
        *status          = SIM_CCD_RETURN;
      }
      else if /* norm sim_data.bip_ch_id for 11.14/12.7 conform */
          ((sim_data.bip_state EQ SIM_BIP_CLOSED) OR
         (stk_cmd->pas_cmd.dev_ids.dest_dev NEQ (sim_data.bip_ch_id | 0x020)))
      {
        /*
         * BIP error, Channel identifier not valid
         */
        *general_result  = RSLT_BEARIND_PERR;
        *add_info_result = ADD_BIP_CHANID_NT_VLD;
        *status          = SIM_CCD_RETURN;
      }
      else
      {
        /*
         * store command parameters
         */
        sim_data.bip_cmd_prms = stk_cmd->pas_cmd.cmd_prms;
      }
    }
  }
  else
  {
    /*
     * incomplete message
     */
    *general_result  = RSLT_ERR_REQ_VAL;
    *add_info_result = ADD_NO_CAUSE;
    *status          = SIM_CCD_RETURN;
    /*
     * set Command Details object values to 0x00
     */
    cmd_details->cmd_nr  = 0;
    cmd_details->cmd_typ = 0;
    cmd_details->cmd_qlf = 0;
  }
} /* stk_bip_decode_stk_command */

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                             |
| STATE   : code                ROUTINE : stk_dti_send_data                   |
+-----------------------------------------------------------------------------+

  PURPOSE : Create and send a DTI Data primitive.

*/

LOCAL void stk_dti_send_data()
{
  T_desc2* temp_desc1;
  /*
   * send DTI data primitive
   */
  PALLOC_DESC2 (dti_data_ind, DTI2_DATA_IND);

#ifdef _SIMULATION_
  dti_data_ind->parameters.p_id       = DTI_PID_UOS;
  dti_data_ind->parameters.st_lines.st_flow      = DTI_FLOW_ON;
  dti_data_ind->parameters.st_lines.st_line_sa   = DTI_SA_ON;
  dti_data_ind->parameters.st_lines.st_line_sb   = DTI_SB_ON;
  dti_data_ind->parameters.st_lines.st_break_len = DTI_BREAK_OFF;
#endif /* _SIMULATION_ */
  switch(sim_data.con_type)
  {

    case SIM_CON_TYPE_UDP:
      MALLOC(temp_desc1, (USHORT)(sizeof(T_desc2) - 1 +
                                  sizeof(T_SRC_DES)));
      memcpy(temp_desc1->buffer,
             &sim_data.udp_parameters,
             sizeof(T_SRC_DES));/*lint !e419  Apparent data overrun for function*/
      temp_desc1->len                = sizeof(T_SRC_DES);
      temp_desc1->next               = sim_data.data_to_send.first;
      sim_data.data_to_send.first    = (ULONG)temp_desc1;
      sim_data.data_to_send.list_len+= temp_desc1->len;
      break;

    case SIM_CON_TYPE_IP:
      dti_data_ind->parameters.p_id = DTI_PID_IP;
      break;

    case SIM_CON_TYPE_SERIAL:
      dti_data_ind->parameters.st_lines.st_flow      = DTI_FLOW_ON;
      dti_data_ind->parameters.st_lines.st_line_sa   = DTI_SA_ON;
      dti_data_ind->parameters.st_lines.st_line_sb   = DTI_SB_ON;
      dti_data_ind->parameters.st_lines.st_break_len = DTI_BREAK_OFF;
      break;
  }
  dti_data_ind->desc_list2       = sim_data.data_to_send;
  sim_data.data_to_send.first    = (ULONG)NULL;
  sim_data.data_to_send.list_len = 0;
  dti_send_data(sim_data.hDTI, 0, 0, 0, dti_data_ind);
} /* stk_dti_send_data() */

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                             |
| STATE   : code                ROUTINE : stk_bip_send_data_terminal_response |
+-----------------------------------------------------------------------------+

  PURPOSE : Send a Terminal Response message for a SEND DATA message.

*/

LOCAL void stk_bip_send_data_terminal_response(UBYTE general_result,
                                               UBYTE add_info_result)
{
  T_sdu*  temp_sdu;
  UBYTE   ccdRet;

  /*
   * memory for encoded message
   */
  MALLOC(temp_sdu, (USHORT)(sizeof(T_sdu) - 1 + MAX_STK_CMD));
  temp_sdu->l_buf = MAX_STK_CMD << 3;
  temp_sdu->o_buf = 0;

  CCD_START;
  {
    MCAST(term_resp, TERM_RESP);
    memset(term_resp, 0, sizeof(T_TERM_RESP));

    /*
     * set Command details
     */
    term_resp->v_cmd_details = TRUE;
    term_resp->cmd_details   = sim_data.bip_tx_cmd_details;
    /*
     * set set Device identities
     */
    term_resp->v_dev_ids        = TRUE;
    term_resp->dev_ids.src_dev  = DEV_SRC_ME;
    term_resp->dev_ids.dest_dev = DEV_DST_SIM;
    /*
     * set Result
     */
    term_resp->v_res   = TRUE;
    term_resp->res.gen = general_result;
    switch(general_result)
    {
      case RSLT_ME_UNAB_PROC:
      case RSLT_NTW_UNAB_PROC:
      case RSLT_LABRWS_GENERIC:
      case RSLT_SS_ERR:
      case RSLT_SMS_ERR:
      case RSLT_USSD_ERR:
      case RSLT_CC_SIM_PRM:
      case RSLT_BEARIND_PERR:
        /*
         * one byte for additional information
         */
        term_resp->res.v_add        = TRUE;
        term_resp->res.add.l_add    = 1 << 3;
        term_resp->res.add.o_add    = 0;
        term_resp->res.add.b_add[0] = add_info_result;
        break;
    }
    /*
     * set Channel Data Length
     */
    term_resp->v_chan_dat_lth = TRUE;
    if ((SIM_CLASS_E_BUFFER_SIZE - sim_data.data_to_send.list_len) > 255)
    {
      /*
       * more than 255 bytes are available in TX buffer
       */
      term_resp->chan_dat_lth = 0xff;
    }
    else
    {
      term_resp->chan_dat_lth = SIM_CLASS_E_BUFFER_SIZE -
                                sim_data.data_to_send.list_len;
    }
    /*
     * encode message
     */
    ccdRet = ccd_codeMsg (CCDENT_SAT,
                          UPLINK,
                          (T_MSGBUF *) temp_sdu,
                          (UBYTE    *) _decodedMsg,
                          TERM_RESP);
  }
  CCD_END;
  /*
   * send Terminal Response
   */
  if (ccdRet NEQ ccdOK)
  {
    TRACE_EVENT_P1("SEND DATA: CCD Coding Error: %d",ccdRet );
  }
  else
  {
    FKT_TerminalResponse (temp_sdu->buf, (USHORT)(temp_sdu->l_buf >> 3));
  }
  MFREE(temp_sdu);
} /* stk_bip_send_data_terminal_response() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_close_dti_connection   |
+--------------------------------------------------------------------+

  PURPOSE : Close DTI connection.

  PARAMETER: The open parameter indicates if the DTI connection is
             still open or already closed.

*/

LOCAL void stk_close_dti_connection(UBYTE close)
{
#ifdef _SIMULATION_
  TRACE_FUNCTION ("stk_close_dti_connection()");
#endif
#ifdef _SIMULATION_
  TRACE_EVENT_P1(" |___-->: sim_data.dti_connection_state=0x%02X", sim_data.dti_connection_state);
#endif
  if (sim_data.dti_connection_state NEQ SIM_DTI_CONNECTION_CLOSED)
  {
     /*
     * close UDP connection
     */
    if (sim_data.con_type EQ SIM_CON_TYPE_UDP)
    {
      /*
       * close currently used port
       */
      if ((sim_data.dti_connection_state NEQ SIM_DTI_CONNECTION_BIND) AND
         (hCommUDP >= VSI_OK))
      {
        PALLOC(udp_closeport_req, UDP_CLOSEPORT_REQ);
        udp_closeport_req->port = sim_data.udp_parameters.src_port[0];
        udp_closeport_req->port = (udp_closeport_req->port << 8);
        udp_closeport_req->port+= sim_data.udp_parameters.src_port[1];
        PSEND(hCommUDP, udp_closeport_req);
      }
      /*
       * release VSI channel
       */
      if (hCommUDP >= VSI_OK)
      {
        vsi_c_close (VSI_CALLER hCommUDP);
      }
      hCommUDP = VSI_ERROR;
    }
    /*
     * disconnect BIP channel
     */
    if (sim_data.bip_state EQ SIM_BIP_CONNECTED)
    {
      sim_data.bip_state = SIM_BIP_OPEN;
      /*
       * stop release timer
       */
      if (sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED)
      {
        if (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
        {
#ifdef _SIMULATION_
          TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif
          TIMER_STOP (sim_handle, SIM_BIP_TIMER);
        }
        sim_data.bip_timer_state = SIM_BIP_TIMER_DISCONNECTED;
      }
    }
    /*
     * close DTI connection
     */
    sim_data.dti_connection_state = SIM_DTI_CONNECTION_CLOSED;
    if (close)
    {
      dti_close(sim_data.hDTI, 0, 0, 0, FALSE);
    }
#ifdef _SIMULATION_
TRACE_EVENT_P1("stk_close_dti_connection: sim_data.dti_connection_state=0x%02X", sim_data.dti_connection_state);
#endif
  }
} /* stk_close_dti_connection() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_close_bip_channel      |
+--------------------------------------------------------------------+

  PURPOSE : Close Bearer Independent Protocol Channel.

*/

LOCAL void stk_close_bip_channel(UBYTE general_result,
                                 UBYTE add_info_result)
{
  T_desc2* temp_desc1;
  T_desc2* temp_desc2;

  if (sim_data.bip_state NEQ SIM_BIP_CLOSED)
  {
    /*
     * set BIP to close
     */
    sim_data.bip_state = SIM_BIP_CLOSED;
    /*
     * stop release timer if used
     */
    if (sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED)
    {
      if (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
      {
#ifdef _SIMULATION_
        TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif
        TIMER_STOP (sim_handle, SIM_BIP_TIMER);
      }
      sim_data.bip_timer_state = SIM_BIP_TIMER_DISCONNECTED;
    }
    /*
     * send Terminal Response
     */
    if (sim_data.bip_tx_state EQ SIM_BIP_TX_SEND)
    {
      stk_bip_send_data_terminal_response(general_result, add_info_result);
      /*
       * close channel is not triggered from a proactive_polling function call
       * so adjust timer and start polling
       */
      stk_start_timer_and_poll();
    }
    /*
     * release suspension
     */
    sim_data.bip_suspend = FALSE;
    /*
     * release RX and TX buffer
     */
    temp_desc1 = (T_desc2*)sim_data.data_to_send.first;
    while(temp_desc1)
    {
      temp_desc2 = temp_desc1;
      temp_desc1 = (T_desc2*)temp_desc1->next;
      MFREE(temp_desc2);
    }
    sim_data.data_to_send.first         = (ULONG)NULL;
    sim_data.data_to_send.list_len      = 0;
    sim_data.prev_data_to_send.first    = (ULONG)NULL;
    sim_data.prev_data_to_send.list_len = 0;
#ifdef _SIMULATION_
    TRACE_EVENT("bip_tx_state = IDLE");
#endif
    sim_data.bip_tx_state               = SIM_BIP_TX_IDLE;
    temp_desc1 = (T_desc2*)sim_data.received_data.first;
    while(temp_desc1)
    {
      temp_desc2 = temp_desc1;
      temp_desc1 = (T_desc2*)temp_desc1->next;
      MFREE(temp_desc2);
    }
    sim_data.received_data.first    = (ULONG)NULL;
    sim_data.received_data.list_len = 0;
    sim_data.received_data_pos      = 0;
#ifdef _SIMULATION_
    TRACE_EVENT("bip_rx_state = IDLE");
#endif
    sim_data.bip_rx_state           = SIM_BIP_RX_IDLE;
  }
} /* stk_close_bip_channel() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_inform_mmi         |
+--------------------------------------------------------------------+

  PURPOSE : Informs MMI if the requested actions have been done.

*/

LOCAL void stk_dti_inform_mmi (UBYTE dti_conn_req, UBYTE bip_conn_req )
{
  UBYTE dti_conn_done;
  UBYTE bip_conn_done;
#if _SIMULATION_
  TRACE_FUNCTION ("stk_dti_inform_mmi()");
#endif
  /*
   * set stutus
   */
  dti_conn_done = 0;
  bip_conn_done = 0;

  if (sim_data.bip_state EQ SIM_BIP_CLOSED)
  {
    bip_conn_done |= SIM_BIP_CLOSE_CHANNEL;
  }
  else
  {
    bip_conn_done |= SIM_BIP_OPEN_CHANNEL;
    /*
     * Only if BIP channel not closed, deal with its suspension state
     */   
    if (sim_data.bip_suspend)
    {
      bip_conn_done |= SIM_BIP_CHANNEL_SUSPENDED;
    }
    else
    {
      bip_conn_done |= SIM_BIP_CHANNEL_RESUMED;
    }
  }
  
  if (sim_data.dti_connection_state  EQ SIM_DTI_CONNECTION_OPEN)
  {
    dti_conn_done = SIM_DTI_CONNECT;
  }

  if (sim_data.dti_connection_state  EQ SIM_DTI_CONNECTION_CLOSED)
  {
    dti_conn_done = SIM_DTI_DISCONNECT;
  }

  /*
   * inform MMI
   */
  if (  /* reguirements REALLY fullfilled in code, then confirm or indicate */
        /* else no reaction at all !! */
       (((bip_conn_req & bip_conn_done) EQ bip_conn_req) OR (bip_conn_req EQ SIM_BIP_UNKNOWN)) AND
        ((dti_conn_req EQ dti_conn_done)OR (dti_conn_req EQ SIM_DTI_UNKNOWN)) AND
       (~(UCHAR)((dti_conn_req EQ SIM_DTI_UNKNOWN) AND (bip_conn_req EQ SIM_BIP_UNKNOWN)))
     ) 
  {
     if (sim_data.sim_dti_req)
     {
        /*
         * send DTI confirm primitive
         */
        PALLOC(sim_dti_cnf, SIM_DTI_CNF);
        sim_dti_cnf->link_id   = sim_data.sim_dti_req->link_id;
        sim_dti_cnf->dti_conn  = dti_conn_done;
        PSEND(hCommMMI, sim_dti_cnf);
        /*
         * free request primitive
         */
        PFREE(sim_data.sim_dti_req);
        sim_data.sim_dti_req = NULL;
      }
      else if (sim_data.sim_bip_req)
      {
        /*
         * send BIP confirm primitive
         */
        PALLOC(sim_bip_cnf, SIM_BIP_CNF);
        sim_bip_cnf->bip_ch_id = sim_data.sim_bip_req->bip_ch_id;
        sim_bip_cnf->bip_conn  = bip_conn_done;
        PSEND(hCommMMI, sim_bip_cnf);
        /*
         * free request primitive
         */
        PFREE(sim_data.sim_bip_req);
        sim_data.sim_bip_req = NULL;
      }
      else
      {
        /*
         * send indication primitive
         */
        PALLOC(sim_dti_bip_ind, SIM_DTI_BIP_IND);
        sim_dti_bip_ind->link_id   = sim_data.link_id;
        sim_dti_bip_ind->dti_conn  = dti_conn_done;        
        sim_dti_bip_ind->bip_ch_id = sim_data.bip_ch_id;
        sim_dti_bip_ind->bip_conn  = bip_conn_done;
        PSEND(hCommMMI, sim_dti_bip_ind);
      }
  } /* and if (requirements fullfilled) */
} /* stk_dti_inform_mmi() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_connection_opened  |
+--------------------------------------------------------------------+

  PURPOSE : Handle CONNECTION OPENED signal from DTILIB.

*/

GLOBAL void stk_dti_connection_opened (void)
{
  TRACE_FUNCTION ("stk_dti_connection_opened()");

  switch(sim_data.dti_connection_state)
  {
    case SIM_DTI_CONNECTION_SETUP:
      sim_data.dti_connection_state = SIM_DTI_CONNECTION_OPEN;
      /*
       * send confirm primitive
       */
      stk_dti_inform_mmi(sim_data.sim_dti_req->dti_conn, (UBYTE) SIM_BIP_UNKNOWN);
      /* fall through */
    case SIM_DTI_CONNECTION_OPEN:
      /*
       * connect BIP with DTI
       */
      if (sim_data.bip_state EQ SIM_BIP_OPEN)
      {
        sim_data.bip_state = SIM_BIP_CONNECTED;
        if (sim_data.bip_release_time EQ SIM_NO_AUTO_RELEASE)
        {
          sim_data.bip_timer_state = SIM_BIP_TIMER_NOT_USED;
        }
        else if (sim_data.bip_suspend)
        {
          sim_data.bip_timer_state = SIM_BIP_TIMER_SUSPENDED;
        }
        else
        {
          sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
        }
      }
      break;

    default:
      /*
       * wrong state
       * so close DTI connection
       * and inform MMI
       */
      TRACE_ERROR("DTI_CONNECTION_OPENED in wrong state");
      stk_close_dti_connection(TRUE);
      stk_dti_inform_mmi(SIM_DTI_DISCONNECT, (UBYTE) SIM_BIP_UNKNOWN);
      break;
  }
  /*
   * reset RX, TX and timer
   */
  sim_data.dti_rx_state = SIM_DTI_RX_IDLE;
  sim_data.dti_tx_state = SIM_DTI_TX_IDLE;
#if 0 /*###jk:OK?*/
  if (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
  {
    sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
#ifdef _SIMULATION_
    TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif
    TIMER_STOP (sim_handle, SIM_BIP_TIMER);
  }
  /*
   * update timer and DTI states
   */
  if ((sim_data.bip_state EQ SIM_BIP_CONNECTED) AND
     (sim_data.bip_rx_state EQ SIM_BIP_RX_IDLE))
  {
    /*
     * start reception
     */
    sim_data.dti_rx_state = SIM_DTI_RX_READY;
    dti_start(sim_data.hDTI, 0, 0, 0);
    /*
     * start timer
     */
    if ((sim_data.bip_timer_state EQ SIM_BIP_TIMER_STOPPED) AND
        (sim_data.bip_tx_state EQ SIM_BIP_TX_IDLE)
       )
    {
      /*
       * no data trafic on the BIP channel,
       * so use the timer
       */
      sim_data.bip_timer_state = SIM_BIP_TIMER_START;
#ifdef _SIMULATION_
      TRACE_EVENT("SIM_BIP_TIMER: start in stk_dti_connection_opened()");
#endif
      TIMER_START (sim_handle, SIM_BIP_TIMER, sim_data.bip_release_time);
    }
  }
 #endif /*###jk:OK?*/
} /* stk_dti_connection_opened() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_connection_closed  |
+--------------------------------------------------------------------+

  PURPOSE : Handle CONNECTION CLOSED signal from DTILIB.

*/

GLOBAL void stk_dti_connection_closed (void)
{
  TRACE_FUNCTION ("stk_dti_connection_closed()");

  /*
   * close DTI connection
   */
  stk_close_dti_connection(FALSE);
  /*
   * inform MMI about disconnection
   */
  stk_dti_inform_mmi(SIM_DTI_DISCONNECT, (UBYTE) SIM_BIP_UNKNOWN);
} /* stk_dti_connection_closed() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_data_received      |
+--------------------------------------------------------------------+

  PURPOSE : Deal with incomming DTI data primitives.

*/

GLOBAL void stk_dti_data_received (T_DTI2_DATA_IND* dti_data_ind)
{
  UBYTE   ccdRet;
  UBYTE   dummy[4];
  T_sdu*  temp_sdu;
  T_desc2* temp_desc1;
  T_desc2* temp_desc2;

 TRACE_FUNCTION ("stk_dti_data_received()");

#ifdef _SIMULATION_
  /*
   * copy bytes of T_SRC_DES struct in extra descriptor
   * this is a requirement of the DTI communication with UDP, but it should
   * not have any side affects in case of communication with other entities
   */
  if ((dti_data_ind->desc_list2.first NEQ (ULONG)NULL) AND
     (dti_data_ind->desc_list2.list_len >= sizeof(T_SRC_DES)))
  {
    T_desc2 *old_desc, *addr_desc, *test_desc, *next_desc;
    USHORT  i, j;

    old_desc = (T_desc2 *)dti_data_ind->desc_list2.first;

    /*
     * build the T_SRC_DES for IP-addresses and ports
     */
    MALLOC(addr_desc, (USHORT)(sizeof(T_desc2) - 1 + sizeof(T_SRC_DES)));
    addr_desc->len = sizeof(T_SRC_DES);
    j = 0;
    for(i=0; i < addr_desc->len; i++)
    {
      while(j >= old_desc->len)
      {
        next_desc = (T_desc2*)old_desc->next;
        MFREE(old_desc);
        old_desc = next_desc;
        j = 0;
      }
      addr_desc->buffer[i] = old_desc->buffer[j];
      j++;
    }

    /*
     *  Build the desc for the data
     */
    if (j < old_desc->len)
    {
      MALLOC(test_desc, (USHORT)(sizeof(T_desc2) - 1 + old_desc->len - j));
      test_desc->len  = old_desc->len - j;
      test_desc->next = old_desc->next;
      for(i=0; i < test_desc->len; i++)
      {
        test_desc->buffer[i] = old_desc->buffer[j];
        j++;
      }
    }
    else
    {
      test_desc = (T_desc2*)old_desc->next;
    }
    MFREE(old_desc);

    dti_data_ind->desc_list2.first = (ULONG)addr_desc;
    addr_desc->next = (ULONG)test_desc;

  }
#endif /* _SIMULATION_ */
  /*
   * take data
   */
  temp_desc1 = (T_desc2*)dti_data_ind->desc_list2.first;
  /*
   * free primitive
   */
  PFREE(dti_data_ind);
  /*
   *
   */
  switch(sim_data.con_type)
  {
/* --67 asd; ###jk test error for image*/
    case SIM_CON_TYPE_UDP:
      /*
       * free first descriptor
       */
      temp_desc2 = temp_desc1;
      if (temp_desc1)
      {
        temp_desc1 = (T_desc2*)temp_desc1->next;
      }
      MFREE(temp_desc2);
      /* fall through */
    case SIM_CON_TYPE_IP:
      /*
       * store data
       */
      if (sim_data.received_data.first EQ (ULONG)NULL)
      {
        sim_data.received_data.first = (ULONG)temp_desc1;
      }
      else
      {
        /*
         * error
         * free received data
         */
        TRACE_ERROR("DTI data received, but still data in RX buffer");
        while(temp_desc1)
        {
          temp_desc2 = temp_desc1;
          temp_desc1 = (T_desc2*)temp_desc1->next;
          MFREE(temp_desc2);
        }
        temp_desc1 = NULL;
      }
      break;

    case SIM_CON_TYPE_SERIAL:
      /*
       * store data
       */
      if (sim_data.received_data.first EQ (ULONG)NULL)
      {
        sim_data.received_data.first = (ULONG)temp_desc1;
      }
      else
      {
        /*
         * error, but concatinate data
         */
        TRACE_ERROR("DTI data received, but still data in RX buffer");
        /*
         * find last descriptor
         */
        temp_desc2 = (T_desc2*)sim_data.received_data.first;
        while(temp_desc2->next NEQ (ULONG)NULL)
        {
          temp_desc2 = (T_desc2*)temp_desc2->next;
        }
        temp_desc2->next = (ULONG)temp_desc1;
      }
      break;
  }
  /*
   * update list length
   */
  while(temp_desc1)
  {
    sim_data.received_data.list_len+= temp_desc1->len;
    temp_desc1                      = (T_desc2*)temp_desc1->next;
  }

  if (sim_data.received_data.list_len)
  {
    /*
     * change state of BIP RX and stop timer
     */
#ifdef _SIMULATION_
    TRACE_EVENT("bip_rx_state = DATA");
#endif
    sim_data.bip_rx_state = SIM_BIP_RX_DATA;
    if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
        (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
       )
    {
      sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
#ifdef _SIMULATION_
      TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif
      TIMER_STOP (sim_handle, SIM_BIP_TIMER);
    }
    /*
     * stop reception
     */
    sim_data.dti_rx_state = SIM_DTI_RX_IDLE;
    dti_stop(sim_data.hDTI, 0, 0, 0);
    /*
     * inform SIM card
     */
    if (sim_data.event_data_avail EQ SIM_EVENT_ENABLE)
    {
      CCD_START;
      {
        MCAST(env_cmd, ENV_CMD);
        memset(env_cmd, 0, sizeof(T_ENV_CMD));

        /*
         * Event Download Command
         */
        env_cmd->v_evd_cmd = TRUE;
        /*
         * Event List
         */
        env_cmd->evd_cmd.v_ev_list        = TRUE;
        env_cmd->evd_cmd.ev_list.c_event  = 1;
        env_cmd->evd_cmd.ev_list.event[0] = EVENT_DATA_AVAIL;
        /*
         * Device Identities
         */
        env_cmd->evd_cmd.v_dev_ids        = TRUE;
        env_cmd->evd_cmd.dev_ids.src_dev  = DEV_SRC_ME;
        env_cmd->evd_cmd.dev_ids.dest_dev = DEV_DST_SIM;
        /*
         * Channel Satus
         */
        env_cmd->evd_cmd.v_chan_stat              = TRUE;
        env_cmd->evd_cmd.chan_stat.chan_id        = sim_data.bip_ch_id & 0x07;
        env_cmd->evd_cmd.chan_stat.chan_stat_inf1 = 0;
        env_cmd->evd_cmd.chan_stat.chan_stat_link = LINK_ESTABL;
        env_cmd->evd_cmd.chan_stat.chan_stat_inf2 = NO_FURTH_INFO;
        /*
         * Channel Data Length
         */
        env_cmd->evd_cmd.v_chan_dat_lth = TRUE;
        if (sim_data.received_data.list_len > 255)
        {
          /*
           * more than 255 bytes are available in RX buffer
           */
          env_cmd->evd_cmd.chan_dat_lth = 0xff;
        }
        else
        {
          env_cmd->evd_cmd.chan_dat_lth = (UBYTE)sim_data.received_data.list_len;
        }
        /*
         * encode message
         */
        MALLOC(temp_sdu, (USHORT)(sizeof(T_sdu) - 1 + MAX_STK_CMD));
        temp_sdu->l_buf = MAX_STK_CMD << 3;
        temp_sdu->o_buf = 0;

        ccdRet = ccd_codeMsg (CCDENT_SAT,
                              UPLINK,
                              (T_MSGBUF *) temp_sdu,
                              (UBYTE    *) _decodedMsg,
                              ENV_CMD);
      }
      CCD_END;

      if ( ccdRet NEQ ccdOK )
      {
        TRACE_EVENT_P1("Data Available: CCD Coding Error: %d",ccdRet );
      }
      else
      {
          FKT_Envelope (dummy, temp_sdu->buf, (USHORT)(temp_sdu->l_buf >> 3), 0);
        /*
         * data received is not triggered from a proactive_polling
         * function call, so adjust timer and start polling
         */
        stk_start_timer_and_poll();
      }
      MFREE(temp_sdu);
    }
  }
} /* stk_dti_data_received() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_tx_buffer_full     |
+--------------------------------------------------------------------+

  PURPOSE : Handle TX BUFFER FULL signal from DTILIB.

*/

GLOBAL void stk_dti_tx_buffer_full (void)
{
  TRACE_FUNCTION ("stk_dti_tx_buffer_full()");

  /*
   * set new DTI state
   */
  sim_data.dti_tx_state = SIM_DTI_TX_IDLE;
} /* stk_dti_tx_buffer_full() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_tx_buffer_ready    |
+--------------------------------------------------------------------+

  PURPOSE : Handle TX BUFFER READY signal from DTILIB.

*/

GLOBAL void stk_dti_tx_buffer_ready (void)
{
  TRACE_FUNCTION ("stk_dti_tx_buffer_ready()");

  /*
   * set new DTI state
   */
  sim_data.dti_tx_state = SIM_DTI_TX_READY;

  /*
   * send confirm primitive to MMI: out of here; actually as the response for 
   * SIM_BIP_CONFIG_REQ
   */
  if ((sim_data.sim_bip_config_req) AND (sim_data.dti_connection_state EQ SIM_DTI_CONNECTION_SETUP))
    {
      PALLOC(sim_bip_config_cnf, SIM_BIP_CONFIG_CNF);
      PSEND(hCommMMI, sim_bip_config_cnf);
      /* primitive no longer needed.. */
      /* and so avoid the second confirm in stk_udp_bind_cnf() */
      PFREE(sim_data.sim_bip_config_req);
      sim_data.sim_bip_config_req = NULL;
      /*
       * set the open state: the connection is now truly opened
       */
      sim_data.dti_connection_state = SIM_DTI_CONNECTION_OPEN;      
    } 
  /*
   * send data
   */
  if (sim_data.bip_tx_state EQ SIM_BIP_TX_SEND)
  {
    /*
     * set new BIP state
     */
#ifdef _SIMULATION_ 
    TRACE_EVENT("bip_tx_state = IDLE");
#endif 
    sim_data.bip_tx_state = SIM_BIP_TX_IDLE;
    /*
     * send DTI data primitive
     */
    stk_dti_send_data();
    /*
     * send Terminal Response
     */
    stk_bip_send_data_terminal_response(sim_data.bip_general_result,
                                        sim_data.bip_add_info_result);
    /*
     * buffer ready is not triggered from a proactive_polling function call
     * so adjust timer and start polling
     */
    stk_start_timer_and_poll();
    /*
     * (re)start release timer
     */
    if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
        (sim_data.bip_rx_state EQ SIM_BIP_RX_IDLE) AND
        ((sim_data.bip_timer_state EQ SIM_BIP_TIMER_STOPPED) OR
        (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)))
    {
      sim_data.bip_timer_state = SIM_BIP_TIMER_START;
#ifdef _SIMULATION_
      TRACE_EVENT("SIM_BIP_TIMER: start in stk_dti_tx_buffer_ready()");
#endif
      TIMER_START (sim_handle, SIM_BIP_TIMER, sim_data.bip_release_time);
    }
  }
} /* stk_dti_tx_buffer_ready() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_bip_send_data      |
+--------------------------------------------------------------------+

  PURPOSE : Handle SEND DATA message from SIM card.

*/

GLOBAL UBYTE stk_dti_bip_send_data (T_sdu* message)
{
  UBYTE   ccdRet;
  UBYTE   func_ret;
  UBYTE   general_result;
  UBYTE   add_info_result;
  UBYTE   status;
  T_desc2* temp_desc1;
  T_desc2* temp_desc2;
  USHORT  temp_pos;
  USHORT  temp_len;

  TRACE_FUNCTION ("stk_dti_bip_send_data()");

  /*
   * initialize value;
   */
  ccdRet          = ccdOK;
  func_ret        = FALSE;
  general_result  = RSLT_PERF_SUCCESS;
  add_info_result = ADD_NO_CAUSE;
  status          = SIM_CCD_OK;

  CCD_START;
  /*
   * decode SIM Toolkit Command
   */
  stk_bip_decode_stk_command(message,
                             &sim_data.bip_tx_cmd_details,
                             &status,
                             &general_result,
                             &add_info_result);  
  /*
   * decode SEND DATA message
   */
  if (status EQ SIM_CCD_OK)
  {
    MCAST(send_data, SEND_DATA);
    memset(send_data, 0, sizeof(T_SEND_DATA));
    /*
     * decode SEND DATA message
     */
    ccdRet = ccd_decodeMsg (CCDENT_SAT,
                            DOWNLINK,
                            (T_MSGBUF *) &sim_data.bip_cmd_prms,
                            (UBYTE    *) _decodedMsg,
                            SEND_DATA);

    if (ccdRet NEQ ccdOK)
    {
      /*
       * handle errors in list
       */
      stk_handle_ccd_error(ccdRet, &status, &general_result, &add_info_result);      
    }
    if (send_data->v_chan_data EQ FALSE)
    {
      /*
       * no Channel Data element present
       * Error, required values are missing
       */
      general_result  = RSLT_ERR_REQ_VAL;
      add_info_result = ADD_NO_CAUSE;
      status          = SIM_CCD_RETURN;
    }
    if (status EQ SIM_CCD_OK)
    {
      if (sim_data.bip_suspend)
      {
        /*
         * channel suspended
         * ME currently unable to process command
         */
        general_result  = sim_data.bip_general_result;
        add_info_result = sim_data.bip_add_info_result;
        status          = SIM_CCD_RETURN;
      }
      else if ((SIM_CLASS_E_BUFFER_SIZE - sim_data.data_to_send.list_len) <
              send_data->chan_data.c_ch_dat_str)
      {
        /*
         * not enough space in tx buffer
         * BIP error
         */
        general_result  = RSLT_BEARIND_PERR;
        add_info_result = ADD_BIP_BUF_SIZ_NAVAIL;
        status          = SIM_CCD_RETURN;
      }
      else
      {
        /*
         * concatenate Channel data
         */
        sim_data.prev_data_to_send = sim_data.data_to_send;
        if (sim_data.data_to_send.first NEQ (ULONG)NULL)
        {
          /*
           * find last descriptor
           */
          temp_desc1 = (T_desc2*)sim_data.data_to_send.first;
          while(temp_desc1->next NEQ (ULONG)NULL)
          {
            temp_desc1 = (T_desc2*)temp_desc1->next;
          }
        }
        else if (send_data->chan_data.c_ch_dat_str)
        {
          /*
           * allocate a new descriptor
           */
          MALLOC(temp_desc1, (USHORT)(sizeof(T_desc2) - 1 +
                             SIM_BIP_TX_DESC_SIZE));
          temp_desc1->next = (ULONG)NULL;
          temp_desc1->offset= 0; /*###jk:OK*/
          temp_desc1->len  = 0;
          temp_desc1->size= 0; /*###jk:OK*/
          sim_data.data_to_send.first    = (ULONG)temp_desc1;
          sim_data.data_to_send.list_len = 0;
        }
        temp_pos = 0;
        while(temp_pos < send_data->chan_data.c_ch_dat_str)
        {
          if (temp_desc1->len >= SIM_BIP_TX_DESC_SIZE) /*lint !e644 temp_desc1 may not have been initialized*/
          {
            /*
             * allocate new desriptor
             */
            temp_desc2 = temp_desc1;
            MALLOC(temp_desc1, (USHORT)(sizeof(T_desc2) - 1 +
                               SIM_BIP_TX_DESC_SIZE));
            temp_desc1->next = (ULONG)NULL;
            temp_desc1->offset = 0; /*###jk:OK*/
            temp_desc1->len  = 0;
            temp_desc1->size = 0; /*###jk:OK*/
            temp_desc2->next = (ULONG)temp_desc1;
          }
          /*
           * calculate length
           */
          temp_len = send_data->chan_data.c_ch_dat_str - temp_pos;
          if (temp_len > (SIM_BIP_TX_DESC_SIZE - temp_desc1->len))
          {
            temp_len = SIM_BIP_TX_DESC_SIZE - temp_desc1->len;
            TRACE_EVENT("sdbsd_5: if (temp_desc1->len >= SIM_BIP_TX_DESC_SIZE)"); /*###jk:tbd*/      
            TRACE_EVENT_P1("sdbsd_5: temp_len = %d", temp_len); /*###jk:tbd*/      
          }
          /*
           * copy data
           */
          memcpy(&temp_desc1->buffer[temp_desc1->len],
                 &send_data->chan_data.ch_dat_str[temp_pos],
                 temp_len);
          temp_pos                      += temp_len;
          temp_desc1->len               += temp_len;
          temp_desc1->size              += temp_len; /*###jk:OK?*/
          sim_data.data_to_send.list_len+= temp_len;
        }
      }
      /*
       * process SEND DATA message
       */
      if (status EQ SIM_CCD_OK)
      {
        /*
         * if alpha identifier or icon identifier is present then
         * forward message to MMI
         */
        if ((send_data->v_alpha_id) OR
           (send_data->v_icon))
        {
          func_ret = TRUE;
        }
        /*
         * check for immediate/store bit
         */
        if (sim_data.bip_tx_cmd_details.cmd_qlf & SIM_QLF_SEND_DATA_1)
        {
          /*
           * send data immediately
           */
          if (sim_data.bip_state EQ SIM_BIP_CONNECTED)
          {
            /*
             * DTI connected
             */
            if (sim_data.dti_tx_state EQ SIM_DTI_TX_READY)
            {
              /*
               * send DTI data primitive
               */
#ifdef _SIMULATION_ 
              TRACE_EVENT("bip_tx_state = IDLE");
#endif 
              sim_data.bip_tx_state = SIM_BIP_TX_IDLE;
              status                = SIM_CCD_RETURN;
              stk_dti_send_data();
            }
            else
            {
              TRACE_EVENT("stbsd_8: else (sim_data.dti_tx_state EQ SIM_DTI_TX_READY)"); /*###jk:tbd*/     
              /*
               * start release timer
               */
#ifdef _SIMULATION_ 
              TRACE_EVENT("bip_tx_state = SEND");
#endif 
              sim_data.bip_tx_state = SIM_BIP_TX_SEND;
              status                = SIM_CCD_DISCARD;
              if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
                  (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
                 )
              {
                sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
#ifdef _SIMULATION_  
                TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif  
                TIMER_STOP (sim_handle, SIM_BIP_TIMER);
              }
            }
            /*
             * (re)start release timer
             */
            if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
                (sim_data.bip_rx_state EQ SIM_BIP_RX_IDLE) AND
                (sim_data.bip_tx_state EQ SIM_BIP_TX_IDLE) AND
                ((sim_data.bip_timer_state EQ SIM_BIP_TIMER_STOPPED) OR
                 (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)))
            {
              sim_data.bip_timer_state = SIM_BIP_TIMER_START;
#ifdef _SIMULATION_  
              TRACE_EVENT("SIM_BIP_TIMER: start in stk_dti_bip_send_data(..)");
#endif 
              TIMER_START (sim_handle, SIM_BIP_TIMER, sim_data.bip_release_time);
            }
          }
          else
          {
            TRACE_EVENT("stbsd_7: else (sim_data.bip_state EQ SIM_BIP_CONNECTED)"); /*###jk:tbd*/
            /*
             * wait for DTI connection
             */
#ifdef _SIMULATION_ 
            TRACE_EVENT("bip_tx_state = SEND");
#endif  
            sim_data.bip_tx_state = SIM_BIP_TX_SEND;
            status                = SIM_CCD_DISCARD;
            if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
                (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
               )
            {
              sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
#ifdef _SIMULATION_ 
              TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif  
              TIMER_STOP (sim_handle, SIM_BIP_TIMER);
            }
            if (sim_data.dti_connection_state EQ SIM_DTI_CONNECTION_CLOSED)
            {
              /*
               * on demand link establishment
               * so forward message to MMI
               */
              func_ret              = TRUE;
            }
          }
        }
        else
        {
          /*
           * store data
           */
          TRACE_EVENT("bip_tx_state = STORE");
          sim_data.bip_tx_state = SIM_BIP_TX_STORE;
          status                = SIM_CCD_RETURN;
          /*
           * stop release timer if used 
           */
          if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
              (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
             )
          {
            sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
            TRACE_EVENT("SIM_BIP_TIMER: stopped");
            TIMER_STOP (sim_handle, SIM_BIP_TIMER);
          }
        }
      }
    }
  } /* if (status EQ SIM_CCD_OK) */

  CCD_END;

  /*
   * send TERMINAL RESPONSE message
   */
  if (status EQ SIM_CCD_RETURN)
  {
    stk_bip_send_data_terminal_response(general_result, add_info_result);
  }
  else
  {
    /*
     * store result codes
     */
    sim_data.bip_general_result  = general_result;
    sim_data.bip_add_info_result = add_info_result;
  }
  /*
   * send return value
   */
  return func_ret;
} /* stk_dti_bip_send_data() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_dti_bip_receive_data   |
+--------------------------------------------------------------------+

  PURPOSE : Handle RECEIVE DATA message from SIM card.

*/

LOCAL UBYTE stk_dti_bip_receive_data (T_sdu* message, UBYTE result_code)
{
  UBYTE   ccdRet;
  UBYTE   func_ret;
  UBYTE   general_result;
  UBYTE   add_info_result;
  UBYTE   status;
  UBYTE   chan_dat_lth;
  T_desc2* temp_desc1;
  T_desc2* temp_desc2;
  T_sdu*  temp_sdu;
  USHORT  temp_pos;
  USHORT  temp_len;

  /*
   * initialize value;
   */
  ccdRet          = ccdOK;
  func_ret        = FALSE;
  general_result  = RSLT_PERF_SUCCESS;
  add_info_result = ADD_NO_CAUSE;
  status          = SIM_CCD_OK;
  chan_dat_lth    = 0; /* jk: initialized because of LINT error */

  CCD_START;
  /*
   * decode SIM Toolkit Command
   */
  stk_bip_decode_stk_command(message,
                             &sim_data.bip_rx_cmd_details,
                             &status,
                             &general_result,
                             &add_info_result);

  /*
   * decode RECEIVE DATA message
   */
  if (status EQ SIM_CCD_OK)
  {
    MCAST(receive_data, RECEIVE_DATA);
    memset(receive_data, 0, sizeof(T_RECEIVE_DATA));

    ccdRet = ccd_decodeMsg (CCDENT_SAT,
                            DOWNLINK,
                            (T_MSGBUF *) &sim_data.bip_cmd_prms,
                            (UBYTE    *) _decodedMsg,
                            RECEIVE_DATA);

#ifdef _SIMULATION_
  TRACE_EVENT_P1("ccdRet@dti_bip_receive_data: %d", ccdRet);
#endif

    if (ccdRet NEQ ccdOK)
    {
      /*
       * handle errors in list
       */
      stk_handle_ccd_error(ccdRet, &status, &general_result, &add_info_result);
    }
    if (receive_data->v_chan_dat_lth EQ FALSE)
    {
      /*
       * no Channel Data Length element present
       * Error, required values are missing
       */
      general_result  = RSLT_ERR_REQ_VAL;
      add_info_result = ADD_NO_CAUSE;
      status          = SIM_CCD_RETURN;
    }
    /*
     * process RECEIVE DATA message
     */
    if (status EQ SIM_CCD_OK)
    {
      /*
       * if alpha identifier or icon identifier is present then
       * forward message to MMI
       */
      if ((receive_data->v_alpha_id) OR
         (receive_data->v_icon))
      {
        func_ret = TRUE;
      }
      if (sim_data.received_data.list_len < receive_data->chan_dat_lth)
      {
        /*
         * can not fill the complete buffer
         */
        general_result  = RSLT_PERF_MISS_INFO;
        add_info_result = ADD_NO_CAUSE;
      }
      status = SIM_CCD_RETURN;
      /*
       * store Channel Data Length
       */
      chan_dat_lth = receive_data->chan_dat_lth;
    }
  }
  CCD_END;
  /*
   * send TERMINAL RESPONSE message
   */
  if (status EQ SIM_CCD_RETURN)
  {
    CCD_START;
    {
      MCAST(term_resp, TERM_RESP);
      memset(term_resp, 0, sizeof(T_TERM_RESP));

      /*
       * set Command details
       */
      term_resp->v_cmd_details = TRUE;
      term_resp->cmd_details   = sim_data.bip_rx_cmd_details;
      /*
       * set set Device identities
       */
      term_resp->v_dev_ids        = TRUE;
      term_resp->dev_ids.src_dev  = DEV_SRC_ME;
      term_resp->dev_ids.dest_dev = DEV_DST_SIM;
      /*
       * set Result
       */
      term_resp->v_res   = TRUE;
      term_resp->res.gen = general_result;
      switch (general_result)
      {
        case RSLT_ME_UNAB_PROC:
        case RSLT_NTW_UNAB_PROC:
        case RSLT_LABRWS_GENERIC:
        case RSLT_SS_ERR:
        case RSLT_SMS_ERR:
        case RSLT_USSD_ERR:
        case RSLT_CC_SIM_PRM:
          /*
           * one byte for additional information
           */
          term_resp->res.v_add        = TRUE;
          term_resp->res.add.l_add    = 1 << 3;
          term_resp->res.add.o_add    = 0;
          term_resp->res.add.b_add[0] = add_info_result;
          break;

        case RSLT_BEARIND_PERR:
          /*
           * one byte for additional information
           */
          term_resp->res.v_add        = TRUE;
          term_resp->res.add.l_add    = 1 << 3;
          term_resp->res.add.o_add    = 0;
          term_resp->res.add.b_add[0] = add_info_result-1;
          break;

        default:
          if (result_code)
            term_resp->res.gen = RSLT_PERF_PART_CMPR;
          break;
      }
      /*
       * set Channel Data
       */
      term_resp->v_chan_data = TRUE;
      switch (general_result)
      {
      case RSLT_PERF_SUCCESS:
      case RSLT_PERF_PART_CMPR:
      case RSLT_PERF_MISS_INFO:
      case RSLT_PERF_MDFY_SIM:
      case RSLT_PERF_MDFIED:
        /*
         * calculate Channel Data String length
         */
        term_resp->chan_data.c_ch_dat_str = SIM_TERM_RESP_MAX_CHANNEL_DATA;
        if (sim_data.received_data.list_len < term_resp->chan_data.c_ch_dat_str)
        {
          term_resp->chan_data.c_ch_dat_str = (UBYTE)sim_data.received_data.list_len;
        }
        if (chan_dat_lth < term_resp->chan_data.c_ch_dat_str)
        {
          term_resp->chan_data.c_ch_dat_str = chan_dat_lth;
        }
        /*
         * copy data
         */
        temp_desc1 = (T_desc2*)sim_data.received_data.first;
        temp_pos = 0;
        while (temp_pos < term_resp->chan_data.c_ch_dat_str)
        {
          /*
           * calculate length
           */
          temp_len = term_resp->chan_data.c_ch_dat_str - temp_pos;
          if (temp_len > (temp_desc1->len - sim_data.received_data_pos))
          {
            temp_len = temp_desc1->len - sim_data.received_data_pos;
          }
          /*
           * copy data
           */
          memcpy(&term_resp->chan_data.ch_dat_str[temp_pos],
                 &temp_desc1->buffer[sim_data.received_data_pos],
                 temp_len);
          /*
           * updata length and position values and descriptors
           */
          temp_pos                       += temp_len;
          sim_data.received_data_pos     += temp_len;
          sim_data.received_data.list_len-= temp_len;
          if (sim_data.received_data_pos >= temp_desc1->len)
          {
            temp_desc2                   = temp_desc1;
            temp_desc1                   = (T_desc2*)temp_desc1->next;
            sim_data.received_data_pos   = 0;
            sim_data.received_data.first = (ULONG)temp_desc1;
            MFREE(temp_desc2);
          }
        }
        break;

      case RSLT_BEARIND_PERR:
      case RSLT_UNKN_DATA:
        term_resp->v_chan_data = FALSE;
        term_resp->chan_data.c_ch_dat_str = 0;
        break;

      default:
        /*
         * if an error is occured then do not provide data
         */
        term_resp->chan_data.c_ch_dat_str = 0;
        break;
      }

      switch (general_result)
      {
      case RSLT_BEARIND_PERR:
      case RSLT_UNKN_DATA:
        break;

      default:
        /*
         * set Channel Data Length
         */
        term_resp->v_chan_dat_lth = TRUE;
        if (sim_data.received_data.list_len > 255)
        {
          /*
           * more than 255 bytes are available in RX buffer
           */
          term_resp->chan_dat_lth = 0xff;
        }
        else
        {
          term_resp->chan_dat_lth = (UBYTE)sim_data.received_data.list_len;
        }
        break;
      }
      /*
       * send Terminal Response
       */
      MALLOC(temp_sdu, (USHORT)(sizeof(T_sdu) - 1 + MAX_STK_CMD));
      temp_sdu->l_buf = MAX_STK_CMD << 3;
      temp_sdu->o_buf = 0;

      ccdRet = ccd_codeMsg (CCDENT_SAT,
                            UPLINK,
                            (T_MSGBUF *) temp_sdu,
                            (UBYTE    *) _decodedMsg,
                            TERM_RESP);
    }
    CCD_END;

    if ( ccdRet NEQ ccdOK )
    {
      TRACE_EVENT_P1("CCD Coding Error: %d",ccdRet );
    }
    else
    {
      FKT_TerminalResponse (temp_sdu->buf, (USHORT)(temp_sdu->l_buf >> 3));
    }
    MFREE(temp_sdu);
  }

  if ((sim_data.bip_rx_state EQ SIM_BIP_RX_DATA) AND
     (sim_data.received_data.list_len EQ 0))
  {
    /*
     * set new BIP state
     */
#ifdef _SIMULATION_
    TRACE_EVENT("bip_rx_state = IDLE");
#endif
    sim_data.bip_rx_state = SIM_BIP_RX_IDLE;
    /*
     * start DTI reception
     */
    if ((sim_data.bip_state EQ SIM_BIP_CONNECTED) AND
       (sim_data.dti_rx_state EQ SIM_DTI_RX_IDLE))
    {
      sim_data.dti_rx_state = SIM_DTI_RX_READY;
      dti_start(sim_data.hDTI, 0, 0, 0);
    }
    /*
     * start release timer
     */
    if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
        (sim_data.bip_timer_state EQ SIM_BIP_TIMER_STOPPED) AND
        (sim_data.bip_tx_state EQ SIM_BIP_TX_IDLE)
       )
    {
         /*
          * no data trafic on the BIP channel,
          * so use the timer
          */
          sim_data.bip_timer_state = SIM_BIP_TIMER_START;
#ifdef _SIMULATION_
          TRACE_EVENT("SIM_BIP_TIMER: start in stk_dti_bip_receive_data(..)");
#endif
          TIMER_START (sim_handle, SIM_BIP_TIMER, sim_data.bip_release_time);
    }
  }
  /*
   * send return value
   */
  return func_ret;
} /* stk_dti_bip_receive_data() */

#ifdef FF_SAT_E
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_udp_bind_cnf           |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive UDP_BIND_CNF.

*/

GLOBAL void stk_udp_bind_cnf (T_UDP_BIND_CNF* udp_bind_cnf)
{
  TRACE_FUNCTION ("stk_udp_bind_cnf()");

  if (sim_data.dti_connection_state EQ SIM_DTI_CONNECTION_BIND)
  {
    if (udp_bind_cnf->err EQ UDP_BIND_NOERROR)
    {
      /*
       * store source port
       */
      sim_data.udp_parameters.src_port[0] =
        ((udp_bind_cnf->port >> 8) & 0x00ff);
      sim_data.udp_parameters.src_port[1] =
        ((udp_bind_cnf->port)      & 0x00ff);
      /*
       * make sending of the confirmation primitive (SIM_BIP_CONFIG_CNF)
       * out of "stk_dti_buffer_ready()" possible
       */
      sim_data.dti_connection_state = SIM_DTI_CONNECTION_SETUP;

      /*###jk:OK? moved & changed from "stk_dti_connection_open()" */
      if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
          (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
         )
      {
        sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
#ifdef _SIMULATION_ 
        TRACE_EVENT("stk_udp_bind_cnf(): SIM_BIP_TIMER: stopped");
#endif  
        TIMER_STOP (sim_handle, SIM_BIP_TIMER);
      }
      /*
       * update timer (if used) and DTI states
       */
      if ((sim_data.bip_state EQ SIM_BIP_CONNECTED) AND
         (sim_data.bip_rx_state EQ SIM_BIP_RX_IDLE))
      {
        /*
         * start reception
         */
        sim_data.dti_rx_state = SIM_DTI_RX_READY;
        dti_start(sim_data.hDTI, 0, 0, 0);
        /*
         * start timer if used
         */
        if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
            (sim_data.bip_tx_state EQ SIM_BIP_TX_IDLE) AND
            (sim_data.bip_timer_state EQ SIM_BIP_TIMER_STOPPED)
           )
        {
          /*
           * no data trafic on the BIP channel,
           * so use the timer
           */
          sim_data.bip_timer_state = SIM_BIP_TIMER_START;
#ifdef _SIMULATION_
          TRACE_EVENT("SIM_BIP_TIMER: start in stk_dti_connection_opened()");
#endif
          TIMER_START (sim_handle, SIM_BIP_TIMER, sim_data.bip_release_time);
        }
      } /*###jk:OK?*/
    } 
    else
    {
      /*
       * can not open UDP port 
       * so disconnect BIP channel from DTI
       */
      stk_close_dti_connection(TRUE);
      /*
       * send confirm primitive
       */
      stk_dti_inform_mmi(SIM_DTI_DISCONNECT, (UBYTE) SIM_BIP_UNKNOWN);
    }
  }
  /*
   * free primitive
   */
  PFREE(udp_bind_cnf);
} /* stk_udp_bind_cnf() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_udp_closeport_cnf      |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive UDP_CLOSEPORT_CNF.

*/

GLOBAL void stk_udp_closeport_cnf (
                    T_UDP_CLOSEPORT_CNF* udp_closeport_cnf)
{
  TRACE_FUNCTION ("stk_udp_closeport_cnf()");

  /*
   * free primitive
   */
  PFREE(udp_closeport_cnf);
} /* stk_udp_closeport_cnf() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_udp_error_ind          |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive UDP_ERROR_IND.

*/

GLOBAL void stk_udp_error_ind (T_UDP_ERROR_IND* udp_error_ind)
{
  TRACE_FUNCTION ("stk_udp_error_ind()");

  /*
   * free primitive
   */
  PFREE(udp_error_ind);
  /*
   * generate error response
   */
  {
    PALLOC(udp_error_res, UDP_ERROR_RES);
    PSEND(hCommUDP, udp_error_res);
  }
} /* stk_udp_error_ind() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_udp_shutdown_ind       |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive UDP_SHUTDOWN_IND.

*/

GLOBAL void stk_udp_shutdown_ind (T_UDP_SHUTDOWN_IND* udp_shutdown_ind)
{
  TRACE_FUNCTION ("stk_udp_shutdown_ind()");

  /*
   * send confirm primitive
   */
  if (hCommUDP < VSI_OK)
  {
    hCommUDP = vsi_c_open (VSI_CALLER UDP_NAME);
  }
  if (hCommUDP >= VSI_OK)
  {
    PALLOC(udp_shutdown_res, UDP_SHUTDOWN_RES);
    PSEND(hCommUDP, udp_shutdown_res);
    /*
     * release VSI channel
     */
    vsi_c_close (VSI_CALLER hCommUDP);
    hCommUDP = VSI_ERROR;
  }
  /*
   * close DTI connection
   */
  if (sim_data.con_type EQ SIM_CON_TYPE_UDP)
  {
    switch(sim_data.dti_connection_state)
    {
      case SIM_DTI_CONNECTION_OPEN:
      case SIM_DTI_CONNECTION_SETUP:
        stk_close_dti_connection(TRUE);
        break;

      default:
        stk_close_dti_connection(FALSE);
        break;
    }
    /*
     * inform ACI about disconnection
     */
    stk_dti_inform_mmi(SIM_DTI_DISCONNECT, (UBYTE) SIM_BIP_UNKNOWN);
  }
} /* stk_udp_shutdown_ind() */
#endif /* FF_SAT_E */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_sim_dti_req            |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_DTI_REQ.

*/

GLOBAL void stk_sim_dti_req (T_SIM_DTI_REQ* sim_dti_req)
{
  UBYTE  dti_conn;

  TRACE_FUNCTION ("stk_sim_dti_req()");

#ifdef _SIMULATION_
  /*
   * set entity_name parameter
   */
switch(sim_dti_req->entity_name)
  {
    case 1:
      sim_dti_req->entity_name = (ULONG)("UDP");
      break;

    case 2:
      sim_dti_req->entity_name = (ULONG)("SND");
      break;

    case 3:
      sim_dti_req->entity_name = (ULONG)("L2R");
      break;

    default:
      sim_dti_req->entity_name = (ULONG)(NULL);
      break;
  }
#endif /* _SIMULATION_ */
  /*
   * store the received primitive
   */
  if (sim_data.sim_dti_req)
  {
    /*
     * free previous primitive before store the new one
     */
    PFREE(sim_data.sim_dti_req);
  }
  sim_data.sim_dti_req = sim_dti_req;

  /*
   * store requested operations
   */
  dti_conn = sim_dti_req->dti_conn;

  switch (dti_conn)
  {
    case SIM_DTI_DISCONNECT: /* close DTI connection */
      {
        switch(sim_data.dti_connection_state)
          {
            case SIM_DTI_CONNECTION_OPEN:
            case SIM_DTI_CONNECTION_SETUP:
              stk_close_dti_connection(TRUE);
              break;
            default:
              stk_close_dti_connection(FALSE);
              break;
          }
        break;
      }
    case SIM_DTI_CONNECT: /* open DTI connection */
      {
        /*
         * if a new DTI connection is requested close the old one before
         */
        switch(sim_data.dti_connection_state)
          {
            case SIM_DTI_CONNECTION_OPEN:
            case SIM_DTI_CONNECTION_SETUP:
              stk_close_dti_connection(TRUE);
              break;
            default:
              stk_close_dti_connection(FALSE);
          }
        /*
         * store relevant data
         */
        sim_data.link_id  = sim_dti_req->link_id;
        sim_data.dti_connection_state = SIM_DTI_CONNECTION_SETUP;
        dti_open(sim_data.hDTI,                 /* DTI handle */
                 0,                             /* instance */
                 0,                             /* interface */
                 0,                             /* channel */
                 0,                             /* queue size */
                 sim_dti_req->dti_direction,    /* direction */
                 FLOW_CNTRL_ENABLED,            /* comm_type */
                 DTI_VERSION_10,                /* version */
                 (UBYTE*)sim_dti_req->entity_name, /* entity name */
                 sim_dti_req->link_id);         /* link identifier */
      }
  }
  /*
   * send confirm primitive
   */
  if (sim_data.sim_dti_req)
  {
    TRACE_EVENT_P1("if(sim_data.sim_dti_req): ~ ->dti_conn=0x%02X", sim_dti_req->dti_conn);

    stk_dti_inform_mmi(sim_dti_req->dti_conn, (UBYTE)SIM_BIP_UNKNOWN);
  }
} /* stk_sim_dti_req() */


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_sim_bip_req            |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_BIP_REQ.

*/

GLOBAL void stk_sim_bip_req (T_SIM_BIP_REQ* sim_bip_req)
{
  UBYTE   bip_conn;
  USHORT  temp_len;
  T_desc2* temp_desc1;
  T_desc2* temp_desc2;

  TRACE_FUNCTION ("stk_sim_bip_req()");

  /*
   * store the received primitive
   */
  if (sim_data.sim_bip_req)
  {
    /*
     * free previous primitive before store the new one
     */
    PFREE(sim_data.sim_bip_req);
  }
  sim_data.sim_bip_req = sim_bip_req;
  /*
   * store requested operations
   */
  bip_conn = sim_bip_req->bip_conn;

  /*
   * resume BIP channel
   */
  if (bip_conn & SIM_BIP_CHANNEL_RESUMED)
  {
    /*
     * set new suspension state
     */
    sim_data.bip_suspend = FALSE;
    /*
     * restart timer if used
     */
    if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
        (sim_data.bip_timer_state EQ SIM_BIP_TIMER_SUSPENDED)
       )
    {
      sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
      if ((sim_data.bip_rx_state EQ SIM_BIP_RX_IDLE) AND
          (sim_data.bip_tx_state EQ SIM_BIP_TX_IDLE)
         )
      {
            /*
             * no data trafic on the BIP channel,
             * so use the timer
             */
            sim_data.bip_timer_state = SIM_BIP_TIMER_START;
#ifdef _SIMULATION_
            TRACE_EVENT("SIM_BIP_TIMER: start in stk_sim_bip_req(..)");
#endif
            TIMER_START (sim_handle, SIM_BIP_TIMER, sim_data.bip_release_time);
      }
    }
  }
  /*
   * close BIP channel
   */
  if (bip_conn & SIM_BIP_CLOSE_CHANNEL)
  {
    stk_close_bip_channel(sim_bip_req->general_result,
                          sim_bip_req->add_info_result);
  }
  /*
   * open BIP channel
   */
  if ((bip_conn & SIM_BIP_OPEN_CHANNEL) AND
     (sim_data.bip_state EQ SIM_BIP_CLOSED))
  {
    /*
     * set new BIP state and
     * store BIP channel identifier
     */
    sim_data.bip_state = SIM_BIP_OPEN;
    sim_data.bip_ch_id = sim_bip_req->bip_ch_id;
    /*
     * store relevant data
     */
    sim_data.bip_release_time =
          (T_TIME)sim_bip_req->release_time * 100; /* convert to msec. */
    if (sim_bip_req->general_result NEQ RSLT_PERF_SUCCESS)
    {
      sim_data.bip_general_result  = sim_bip_req->general_result;
      sim_data.bip_add_info_result = sim_bip_req->add_info_result;
    }
  }
  /*
   * suspend BIP channel
   */
  if (bip_conn & SIM_BIP_CHANNEL_SUSPENDED)
  {
    /*
     * set new suspension state
     */
    sim_data.bip_suspend = TRUE;
    /*
     * stop timer if timer is used
     */
    if (sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED)
    {
      if (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
      {
        sim_data.bip_timer_state = SIM_BIP_TIMER_SUSPENDED;
#ifdef _SIMULATION_
        TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif
        TIMER_STOP (sim_handle, SIM_BIP_TIMER);
      }
      else if (sim_data.bip_timer_state EQ SIM_BIP_TIMER_STOPPED)
      {
        sim_data.bip_timer_state = SIM_BIP_TIMER_SUSPENDED;
      }
    }
    /*
     * store result codes
     */
    sim_data.bip_general_result  = sim_bip_req->general_result;
    sim_data.bip_add_info_result = sim_bip_req->add_info_result;
    /*
     * inform SIM card
     */
    if (sim_data.bip_tx_state EQ SIM_BIP_TX_SEND)
    {
      /*
       * free data of last SEND DATA message
       */
      temp_desc1            = (T_desc2*)sim_data.data_to_send.first;
      sim_data.data_to_send = sim_data.prev_data_to_send;
      if (sim_data.data_to_send.first EQ (ULONG)NULL)
      {
        while(temp_desc1)
        {
          temp_desc2 = temp_desc1;
          temp_desc1 = (T_desc2*)temp_desc1->next;
          MFREE(temp_desc2);
        }
      }
      else
      {
        temp_len = 0;
        while((temp_desc1) AND
              (temp_len + temp_desc1->len) < sim_data.data_to_send.list_len)
        {
          temp_len  += temp_desc1->len;
          temp_desc1 = (T_desc2*)temp_desc1->next;
        }
        if (temp_desc1)
        {
          temp_desc1->len  = sim_data.data_to_send.list_len - temp_len;
          temp_desc2       = (T_desc2*)temp_desc1->next;
          temp_desc1->next = (ULONG)NULL;
          temp_desc1       = temp_desc2;
          while(temp_desc1)
          {
            temp_desc2 = temp_desc1;
            temp_desc1 = (T_desc2*)temp_desc1->next;
            MFREE(temp_desc2);
          }
        }
      }
      /*
       * set new BIP TX state
       */
      if (sim_data.data_to_send.first EQ (ULONG)NULL)
      {
#ifdef _SIMULATION_
        TRACE_EVENT("bip_tx_state = IDLE");
#endif
        sim_data.bip_tx_state = SIM_BIP_TX_IDLE;
      }
      else
      {
#ifdef _SIMULATION_
        TRACE_EVENT("bip_tx_state = STORE");
#endif
        sim_data.bip_tx_state = SIM_BIP_TX_STORE;
        if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
            (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
           )
        {
          sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
#ifdef _SIMULATION_
          TRACE_EVENT("SIM_BIP_TIMER: stopped");
#endif
          TIMER_STOP (sim_handle, SIM_BIP_TIMER);
        }
      }
      /*
       * send Terminal Response
       */
      stk_bip_send_data_terminal_response(sim_bip_req->general_result,
                                          sim_bip_req->add_info_result);
      /*
       * suspension is not triggered from a proactive_polling function call
       * so adjust timer and start polling
       */
      stk_start_timer_and_poll();
    }
  }
  /*
   * send confirm primitive
   */
  if (sim_data.sim_bip_req)
  {
    stk_dti_inform_mmi((UBYTE) SIM_DTI_UNKNOWN, sim_bip_req->bip_conn);
  }
} /* stk_sim_bip_req() */


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_sim_bip_config_req     |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_BIP_CONFIG_REQ.

*/

GLOBAL void stk_sim_bip_config_req(T_SIM_BIP_CONFIG_REQ * sim_bip_config_req)
{
  TRACE_FUNCTION ("stk_sim_bip_config_req()");
  /*
   * store the received primitive
   */
  if (sim_data.sim_bip_config_req)
  {
    /*
     * free previous primitive before store the new one
     */
    PFREE(sim_data.sim_bip_config_req);
  }
  sim_data.sim_bip_config_req = sim_bip_config_req;
  /*
   * store relevant data
   */
  sim_data.con_type                   = sim_bip_config_req->con_type;

#if 0
  sim_data.udp_parameters.src_ip[0]   =
      (UBYTE)((sim_bip_config_req->local_ip >> 24) & 0x000000ff);
  sim_data.udp_parameters.src_ip[1]   =
      (UBYTE)((sim_bip_config_req->local_ip >> 16) & 0x000000ff);
  sim_data.udp_parameters.src_ip[2]   =
      (UBYTE)((sim_bip_config_req->local_ip >>  8) & 0x000000ff);
  sim_data.udp_parameters.src_ip[3]   =
      (UBYTE)((sim_bip_config_req->local_ip)       & 0x000000ff);
#else
sim_data.udp_parameters.src_ip[3]   =
    (UBYTE)((sim_bip_config_req->local_ip >> 24) & 0x000000ff);
sim_data.udp_parameters.src_ip[2]   =
    (UBYTE)((sim_bip_config_req->local_ip >> 16) & 0x000000ff);
sim_data.udp_parameters.src_ip[1]   =
    (UBYTE)((sim_bip_config_req->local_ip >>  8) & 0x000000ff);
sim_data.udp_parameters.src_ip[0]   =
    (UBYTE)((sim_bip_config_req->local_ip)       & 0x000000ff);
#endif

  sim_data.udp_parameters.des_ip[0]   =
      (UBYTE)((sim_bip_config_req->destination_ip >> 24) & 0x000000ff);
  sim_data.udp_parameters.des_ip[1]   =
      (UBYTE)((sim_bip_config_req->destination_ip >> 16) & 0x000000ff);
  sim_data.udp_parameters.des_ip[2]   =
      (UBYTE)((sim_bip_config_req->destination_ip >>  8) & 0x000000ff);
  sim_data.udp_parameters.des_ip[3]   =
      (UBYTE)((sim_bip_config_req->destination_ip)       & 0x000000ff);

#if 0
  sim_data.udp_parameters.des_port[0] =
      (UBYTE)((sim_bip_config_req->destination_port >> 8) & 0x00ff);
  sim_data.udp_parameters.des_port[1] =
      (UBYTE)((sim_bip_config_req->destination_port)      & 0x00ff);
#else
  sim_data.udp_parameters.des_port[1] =
      (UBYTE)((sim_bip_config_req->destination_port >> 8) & 0x00ff);
  sim_data.udp_parameters.des_port[0] =
      (UBYTE)((sim_bip_config_req->destination_port)      & 0x00ff);
#endif
   
    /*
     * UDP connection
     */
    if (sim_data.con_type EQ SIM_CON_TYPE_UDP)
    {
      /*
       * open VSI channel to UDP
       */
      if (hCommUDP < VSI_OK)            
      {
        TRACE_EVENT("if(hCommUDP < VSI_OK)");
        if ((hCommUDP = vsi_c_open (VSI_CALLER UDP_NAME)) < VSI_OK)
        {
          TRACE_EVENT("if ((hCommUDP = vsi_c_open (VSI_CALLER UDP_NAME)) < VSI_OK)");
          /*
           * can not open VSI channel
           * so act as if DTI close was requested
           */
          sim_data.sim_dti_req->dti_conn = SIM_DTI_DISCONNECT;
          TRACE_EVENT_P1(": sim_data.sim_dti_req->dti_conn=0x%02X", sim_data.sim_dti_req->dti_conn);
        }
      }
      /*
       * send UDP_BIND_REQ
       */
      if (hCommUDP >= VSI_OK)
      {
        PALLOC(udp_bind_req, UDP_BIND_REQ);
        sim_data.dti_connection_state = SIM_DTI_CONNECTION_BIND;
        udp_bind_req->port            = UDP_AUTOASSIGN_PORT;
        PSEND(hCommUDP, udp_bind_req);
        /*
         * send confirm primitive:
         * will be sent out of "stk_dti_buffer_ready()" function in case of success,
         * in case of udp_bind_cnf failure only indication primitive will be sent
         * out of "stk_udp_bind_cnf" to MMI instead.
         */
      }
    }
    /*
     * bearer level connection
     */
    else
    {
      /*###jk:OK? moved & changed from "stk_dti_connection_open()" */
      if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
          (sim_data.bip_timer_state EQ SIM_BIP_TIMER_START)
         )
      {
        sim_data.bip_timer_state = SIM_BIP_TIMER_STOPPED;
#ifdef _SIMULATION_ 
        TRACE_EVENT("stk_udp_bind_cnf(): SIM_BIP_TIMER: stopped");
#endif  
        TIMER_STOP (sim_handle, SIM_BIP_TIMER);
      }
      /*
       * update timer (if used) and DTI states
       */
      if ((sim_data.bip_state EQ SIM_BIP_CONNECTED) AND
         (sim_data.bip_rx_state EQ SIM_BIP_RX_IDLE))
      {
        /*
         * start reception
         */
        sim_data.dti_rx_state = SIM_DTI_RX_READY;
        dti_start(sim_data.hDTI, 0, 0, 0);
        /*
         * start timer if used
         */
        if ((sim_data.bip_timer_state NEQ SIM_BIP_TIMER_NOT_USED) AND
            (sim_data.bip_tx_state EQ SIM_BIP_TX_IDLE) AND
            (sim_data.bip_timer_state EQ SIM_BIP_TIMER_STOPPED)
           )
        {
          /*
           * no data trafic on the BIP channel,
           * so use the timer
           */
          sim_data.bip_timer_state = SIM_BIP_TIMER_START;
#ifdef _SIMULATION_
          TRACE_EVENT("SIM_BIP_TIMER: start in stk_dti_connection_opened()");
#endif
          TIMER_START (sim_handle, SIM_BIP_TIMER, sim_data.bip_release_time);
        }
      } /*###jk:OK?*/ 

      /*
       * make sending of the confirmation primitive (SIM_BIP_CONFIG_CNF)
       * out of "stk_dti_buffer_ready()" possible
       */      
       sim_data.dti_connection_state = SIM_DTI_CONNECTION_SETUP;

      /*
       * send confirm primitive:
       * will be sent out of "stk_dti_buffer_ready()" function in order to
       * prevent sending of the data to connected neighbour DTI-entity before
       * this entity is ready to receive data.
       */      
#if 0 /*###jk:OK? -> */
      /*
       * send confirm primitive
       */
      if (sim_data.sim_bip_config_req)
      {
        PALLOC(sim_bip_config_cnf, SIM_BIP_CONFIG_CNF);
        PSEND(hCommMMI, sim_bip_config_cnf);
      }
#endif
    }
} /* stk_bip_config_req() */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_sim_eventlist_req      |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_EVENTLIST_REQ.

*/

GLOBAL void stk_sim_eventlist_req (
                    T_SIM_EVENTLIST_REQ* sim_eventlist_req)
{
  TRACE_FUNCTION ("stk_sim_eventlist_req()");

  /*
   * store new state of Data available event
   */
  sim_data.event_data_avail = sim_eventlist_req->event_data_avail;
  /*
   * free primitive
   */
  PFREE(sim_eventlist_req);
  /*
   * send confirm primitive
   */
  {
    PALLOC(sim_eventlist_cnf, SIM_EVENTLIST_CNF);
    sim_eventlist_cnf->event_data_avail = sim_data.event_data_avail;
    PSEND(hCommMMI, sim_eventlist_cnf);
  }
} /* stk_sim_eventlist_req() */
#endif /* FF_SAT_E */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_sim_toolkit_res        |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_TOOLKIT_RES. MMI sends a
            Terminal Response Message to SIM toolkit.

*/

GLOBAL void stk_sim_toolkit_res (T_SIM_TOOLKIT_RES * sim_toolkit_res)
{
  TRACE_FUNCTION ("stk_sim_toolkit_res()");

  if (sim_data.ext_sat_cmd)
  {
    FKT_TerminalResponse (sim_toolkit_res->stk_cmd.cmd,
                          (USHORT)(sim_toolkit_res->stk_cmd.l_cmd>>3));
    PFREE (sim_toolkit_res);

    sim_data.ext_sat_cmd = FALSE;
    stk_start_timer_and_poll();
  }
  else
  {
    TRACE_EVENT("no outstanding TR");
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_sim_toolkit_req        |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_TOOLKIT_REQ. MMI sends an
            Envelope Message to SIM toolkit.

*/

GLOBAL void stk_sim_toolkit_req (T_SIM_TOOLKIT_REQ * sim_toolkit_req)
{
  PALLOC (sim_toolkit_cnf, SIM_TOOLKIT_CNF);

  sim_toolkit_cnf->stk_cmd.o_cmd = 0;
  sim_toolkit_cnf->req_id = sim_toolkit_req->req_id;

  TRACE_FUNCTION ("stk_sim_toolkit_req()");

  switch (sim_toolkit_req->source)  // check valid source
  {
  case SRC_MMI:
  case SRC_SMS:
    break;
  default:
    TRACE_EVENT ("SIM_TOOLKIT_REQ: invalid source");
    PFREE (sim_toolkit_cnf);
    PFREE (sim_toolkit_req);
    return;
  }
  /*
   * Forward envelope command to SIM toolkit
   */
  sim_toolkit_cnf->cause = FKT_Envelope (sim_toolkit_cnf->stk_cmd.cmd,
                                         sim_toolkit_req->stk_cmd.cmd,
                                         (USHORT)(sim_toolkit_req->stk_cmd.l_cmd >> 3), 
                                          NOT_PRESENT_16BIT);

  /*
   * Special treatment of SW1 is required for Call Control/MO-SM Control by SIM
   */
  if (sim_toolkit_cnf->cause NEQ SIM_NO_ERROR)
  {
    switch (sim_toolkit_req->stk_cmd.cmd[0])  /* ENVELOPE tag */
    {
    case 0xD4:  /* Call Control */
    case 0xD5:  /* MO-SM Control */
      if (sim_data.sw1 EQ 0x6F OR sim_data.sw1 EQ 0x92) /* Card problem */
        sim_toolkit_cnf->cause = SIM_NO_ERROR;
      break;
    default:
      break;
    }
  }

  if (sim_data.sim_data_len > 0)
  {
      sim_toolkit_cnf->stk_cmd.l_cmd = stk_l_cmd;
	    stk_l_cmd = 0;
  }
  else
      sim_toolkit_cnf->stk_cmd.l_cmd = 0;

  /*
   * send confirmation to requesting entity
   */
  if (sim_toolkit_req->source EQ SRC_MMI)
  {
    PSENDX (MMI, sim_toolkit_cnf);
  }
  else
  {
    PSENDX (SMS, sim_toolkit_cnf);
  }
  PFREE (sim_toolkit_req);
  stk_start_timer_and_poll();
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_file_update_res        |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_FILE_UPDATE_RES. A File Change
            Notification is responded.

*/

GLOBAL void stk_file_update_res (T_SIM_FILE_UPDATE_RES * file_update_res)
{
  UBYTE *p_res;     // access to result code

  TRACE_FUNCTION ("stk_file_update_res()");

  if (file_update_res->source EQ SRC_MMI)
    sim_data.file_change_resp &= ~1;
  else if (file_update_res->source EQ SRC_SMS)
    sim_data.file_change_resp &= ~2;
  else if (file_update_res->source EQ SRC_MM)
    sim_data.file_change_resp &= ~4;
  else
  {
    PFREE (file_update_res);
    return;
  }
  p_res = &sim_data.stk_response[sim_data.stk_response[1] + 8];
  if (file_update_res->fu_rsc EQ SIM_FU_SUCC_ADD)
    *p_res = STK_RES_SUCC_ADD_EF_READ;

  if (sim_data.file_change_resp EQ 0)
  {
    FKT_TerminalResponse (sim_data.stk_response, (USHORT)sim_data.stk_resp_len);
    stk_start_timer_and_poll();
  }
  PFREE (file_update_res);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_timeout                |
+--------------------------------------------------------------------+

  PURPOSE : Process the timeout of a timer established by the SAT
            command TIMER MANAGEMENT.

*/

static const  UBYTE timer_env[] = {
  STK_TIMER_EXPIRATION_TAG,
  STK_DEVICE_IDENTITY_LEN+STK_TIMER_ID_LEN+STK_TIMER_VALUE_LEN+6,
  STK_DEVICE_IDENTITY_TAG|STK_COMPREHENSION_REQUIRED, STK_DEVICE_IDENTITY_LEN, 0x82, 0x81,
  STK_TIMER_ID_TAG|STK_COMPREHENSION_REQUIRED, STK_TIMER_ID_LEN, 0,
  STK_TIMER_VALUE_TAG|STK_COMPREHENSION_REQUIRED, STK_TIMER_VALUE_LEN, 0, 0, 0
};

extern UBYTE pending_timers[];
extern UBYTE next_pos_to_fill;
extern UBYTE next_pos_to_send;


GLOBAL void stk_timeout (USHORT index)
{
  UBYTE env[sizeof(timer_env)];
  UBYTE dummy[4];
  USHORT error;

  TRACE_FUNCTION("stk_timeout");
#ifdef FF_SAT_E
  /*
   * handle BIP timeout
   */
  if (index EQ SIM_BIP_TIMER)
  {
    /*
     * close DTI connection
     */
    switch(sim_data.dti_connection_state)
    {
      case SIM_DTI_CONNECTION_OPEN:
      case SIM_DTI_CONNECTION_SETUP:
        stk_close_dti_connection(TRUE);
        break;

      default:
        stk_close_dti_connection(FALSE);
        break;
    }
    /*
     * close BIP channel and inform MMI
     */
    stk_close_bip_channel(RSLT_BEARIND_PERR, ADD_BIP_CHAN_CLOSD);
    stk_dti_inform_mmi(SIM_DTI_DISCONNECT, SIM_BIP_CLOSE_CHANNEL);
    return;
  }
#endif /* FF_SAT_E */

  if ((unsigned)(--index) >= MAX_SAT_TIMER)   /* index range 0..7 */
    return;

  if (sim_data.timer[index].active)
  {
    memcpy (env, timer_env, sizeof(timer_env));
    env[8] = (UBYTE)(index + 1);  /* Timer number range is 1..8 */
    env[11] = sim_data.timer[index].hour;
    env[12] = sim_data.timer[index].minute;
    env[13] = sim_data.timer[index].second;
  
    error = FKT_Envelope (dummy, env, sizeof(timer_env), 0);
//TISH, test patch for OMAPS00179771: SATK: Timer Expiration, modified by Jinshu Wang, 2008-09-01
//start
#if 0
    if (error EQ SIM_NO_ERROR)
      stk_start_timer_and_poll();
#else
    if (error EQ SIM_NO_ERROR)
	{
      stk_start_timer_and_poll();
	    sim_data.timer[index].active = FALSE; //modified by Jinshu Wang, 2008-09-04
	  if(sim_data.chk_sat_avail)
	  {
		sim_data.chk_sat_avail = FALSE;
		stk_proactive_polling();
		}
	return;	 //modified by Jinshu Wang, 2008-09-04
	}
#endif
//end
   /*
    * If SIM response is busy(9300), we have to once retry sending 
    * timer-expiry envelope after SIM becomes OK on getting a TR
   */  
   if (error EQ SIM_CAUSE_SAT_BUSY)
   {
     pending_timers[next_pos_to_fill] = (UBYTE) index;
     if (8 == next_pos_to_fill)
     {
       next_pos_to_fill = 0;
     }
     else
     {
       next_pos_to_fill++;
     }
   }
    sim_data.timer[index].active = FALSE;
  }
}

#ifdef TI_PS_FF_AT_P_CMD_CUST
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (8419)       MODULE  : SIM_STK                    |
| STATE   : code                ROUTINE : stk_sim_refresh_user_res   |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive SIM_REFRESH_USER_RES. MMI sends a
            Response Message to SIM_TOOLKIT_IND.
            This Primitive should not occur when cust_mode is 0

*/

GLOBAL void stk_sim_refresh_user_res (T_SIM_REFRESH_USER_RES * sim_refresh_user_res)
{
  TRACE_FUNCTION ("stk_sim_refresh_user_res()");

  /* primitive should not occur for cust_mode 0 */
  if (sim_data.cust_mode EQ 0)
  {
    //Handle error condition
    TRACE_FUNCTION_P1 ("!!!!Incorrect operation: Unexpected mode: cust_mode = %d !!!!",sim_data.cust_mode);
    TRACE_FUNCTION ("Primitive should not occur if cust_mode = 0");
    //MFREE (sim_data.context_switch_ptr); Don't free context as it should be freed by other thread. i.e. stk_proactive_polling()
    PFREE (sim_refresh_user_res);
    return;
  }

  /* check that we are expecting primitive */
  if ( sim_data.user_confirmation_expected EQ FALSE )
  {
    //Handle error condition
    TRACE_FUNCTION ("!!!!Incorrect operation: user_confirmation_expected is FALSE !!!!");
    TRACE_FUNCTION ("Primitive should only occur if user_confirmation_expected is TRUE");
    //MFREE (sim_data.context_switch_ptr); Don't free context switch as setup can not be guaranteed to be correct.
    PFREE (sim_refresh_user_res);
    return;
  }
  else
  {
    //Reset user_confirmation_expected
    sim_data.user_confirmation_expected = FALSE;
  }


  if ((sim_refresh_user_res->user_accepts) EQ FALSE)
  {
    TRACE_FUNCTION ("User REJECTS Refresh Request");

    FKT_TerminalResponse (sim_refresh_user_res->stk_cmd.cmd,
                          (USHORT)(sim_refresh_user_res->stk_cmd.l_cmd>>3));
    sim_data.ext_sat_cmd = FALSE;
    stk_start_timer_and_poll();

    //process_sim_refresh() automatically frees the signal.
    //As we are not calling process_sim_refresh() we need to handle the freeing
    TRACE_ASSERT(sim_data.context_switch_ptr->sig_ptr);
    PFREE (sim_data.context_switch_ptr->sig_ptr); 
  }
  else
  {
    TRACE_FUNCTION ("User ACCEPTS Refresh Request");
    process_sim_refresh(sim_data.context_switch_ptr);
    TRACE_FUNCTION ("stk_sim_refresh_user_res() send end of SAT session indicator");
    if ((sim_data.term_resp_sent) AND (sim_data.sat_session))
    {
      PALLOC (sim_toolkit_ind, SIM_TOOLKIT_IND);
      memset (sim_toolkit_ind, 0, sizeof (T_SIM_TOOLKIT_IND));
#ifdef _SIMULATION_
      TRACE_EVENT("SAT session ended");
#endif
      sim_data.sat_session    = FALSE;
      sim_data.term_resp_sent = FALSE;
      PSENDX (MMI, sim_toolkit_ind);
    }

  }
  TRACE_ASSERT(sim_data.context_switch_ptr);
  MFREE (sim_data.context_switch_ptr);
  sim_data.context_switch_ptr = NULL;

  PFREE (sim_refresh_user_res);
  TRACE_FUNCTION ("stk_sim_refresh_user_res() exited");
}
#endif /* TI_PS_FF_AT_P_CMD_CUST */

#endif