view src/g23m-gsm/sim/sim_stk.c @ 223:740a8e8fc9d7

startup sync logic rework for the new PWON button boot scheme Previously we added logic to the MMI task to hold off PEI init until R2D is running, and then extended that condition to wait for FCHG init too. However, the dependencies of MMI upon R2D and FCHG don't start until mmiInit(), and that call is driven by Switch_ON() code, hence the wait for R2D and FCHG init can be made in that code path instead of the MMI task. Furthermore, with our new way of signaling PWON button boot to MMI, we need a new wait to ensure that the MMI task is up - previously this assurance was provided by the wait for Kp pointers to be set. Solution: revert our previous PEI init hold-off additions to MMI, add a new flag indicating MMI task init done, and put the combined wait for all needed conditions into our new PWON button boot code in power.c.
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 27 Apr 2021 06:24:52 +0000
parents fa8dc04885d8
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