view src/g23m-gsm/sim/uicc_fkt.c @ 682:17b7b92e7dba

uartfax.c: fix for old Openmoko bug with Auto-CTS Openmoko made the change of enabling hardware assisted CTS flow control in the UART when RTS/CTS flow control is used - it is a change which we have retained in FreeCalypso - but they forgot to turn this hw mode off if RTS/CTS flow control is deselected at the application level. We (FreeCalypso) are now fixing the latter defect ourselves.
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 26 Jun 2020 02:53:02 +0000
parents 27a4235405c6
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GSM-F&D (8411)
|  Modul   :  SIM_FKT
+----------------------------------------------------------------------------- 
|  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 wrapping functions for the
|             SIM application.
+----------------------------------------------------------------------------- 
*/ 

#ifndef SIM_FKT_C
#define SIM_FKT_C

#define ENTITY_SIM

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

#include <string.h>
#include "typedefs.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 "8010_136_SIMDRV_SAP_inline.h"

/*==== EXPORT =====================================================*/

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

/*==== VARIABLES ==================================================*/
GLOBAL USHORT    stk_l_cmd = 0;
/*==== FUNCTIONS ===================================================*/

/* Implements Measure# 13 */
/*
+---------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_FKT                     |
| STATE   : code                ROUTINE : FKT_ChangeCHV_n_UnblockCHV  |
+---------------------------------------------------------------------+

  PURPOSE : Wrapping function for the SIM driver call SIM_ChangeCHV and 
            SIM_UnblockCHV

*/

LOCAL USHORT FKT_ChangeCHV_n_UnblockCHV ( UBYTE            * oldPin_UnblkCHV,
                                          UBYTE            * newPin_CHV,
                                          UBYTE              pinId_chvType,
                                          UBYTE              inst_code) 
{
  USHORT size = 0;
  USHORT sw1sw2;

  U8     reader_id;
  U8     i;
  U8     data[2*MAX_PIN_LEN];

  UBYTE  response[SIMDRV_MAX_RESULT];

  T_SIMDRV_cmd_header    cmd_header;
  T_SIMDRV_data_info     data_info;
  T_SIMDRV_result_info   result_info;

  TRACE_FUNCTION ("FKT_ChangeCHV_n_UnblockCHV()");

  reader_id      = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = inst_code;      
  cmd_header.p1  = 0;
  cmd_header.p2  = pinId_chvType;  
  
  for (i=0;i<2*MAX_PIN_LEN;i++)
  {
    if (i < MAX_PIN_LEN)
      data[i] = oldPin_UnblkCHV[i];
    else
      data[i] = newPin_CHV[i-MAX_PIN_LEN];
  }
  
  data_info.data   = (U8 *)data;
  data_info.c_data = sizeof(data);
  
  result_info.result   = response;
  result_info.c_result = size;
  result_info.len      = NOT_PRESENT_16BIT;
  
  sw1sw2 =  simdrv_xch_apdu(reader_id, cmd_header, data_info, &result_info);
  
  return FKT_convert_error (sw1sw2,result_info.c_result);
}
  
  
/* Implements Measure# 16 */
/*
+------------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_FKT                        |
| STATE   : code                ROUTINE : FKT_Invalidate_n_Rehabilitate  |
+------------------------------------------------------------------------+

  PURPOSE : Wrapping function for the SIM driver call SIM_Invalidate and 
            SIM_Rehabilitate.

*/

LOCAL USHORT FKT_Invalidate_n_Rehabilitate ( UBYTE inst_code) 
{
  USHORT   size = 0;
  USHORT   sw1sw2;

  U8       reader_id;

  UBYTE    response[SIMDRV_MAX_RESULT];

  T_SIMDRV_cmd_header    cmd_header;
  T_SIMDRV_data_info     data_info;
  T_SIMDRV_result_info   result_info;
  
  TRACE_FUNCTION ("FKT_Invalidate_n_Rehabilitate()");
  
  reader_id      = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = inst_code;
  cmd_header.p1  = 0;
  cmd_header.p2  = 0;
  
  data_info.data   = NULL;
  data_info.c_data = 0;
  
  result_info.result   = response;
  result_info.c_result = size;
  result_info.len      = NOT_PRESENT_16BIT;
  
  sw1sw2 = simdrv_xch_apdu(reader_id,cmd_header,data_info,&result_info);

  if (sw1sw2 EQ 0x9810)   /* already invalidated */
    return SIM_NO_ERROR;
  
  return FKT_convert_error (sw1sw2,result_info.c_result);
}
  
  
/* Implements Measure# 17 */
/*
+----------------------------------------------------------------------+
| PROJECT : GSM-PS (6302)       MODULE  : SIM_FKT                      |
| STATE   : code                ROUTINE : FKT_DisableCHV_n_EnableCHV   |
+----------------------------------------------------------------------+

  PURPOSE : Wrapping function for the SIM driver call SIM_DisableCHV  and 
            SIM_EnableCHV

*/

LOCAL USHORT FKT_DisableCHV_n_EnableCHV (UBYTE  * pin, UBYTE inst_code) 
{
  USHORT  size = 0;
  USHORT  sw1sw2;

  U8      reader_id;

  T_SIMDRV_cmd_header   cmd_header;
  T_SIMDRV_data_info    data_info;
  T_SIMDRV_result_info  result_info;

  UBYTE   response[SIMDRV_MAX_RESULT];

  TRACE_FUNCTION ("FKT_DisableCHV_n_EnableCHV()");

  reader_id      = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = inst_code; 
  cmd_header.p1  = 0;
  cmd_header.p2  = 1;

  data_info.data   = (U8 *)pin;
  data_info.c_data = MAX_PIN_LEN;
  
  result_info.result   = response;
  result_info.c_result = size;
  result_info.len      = NOT_PRESENT_16BIT;

  sw1sw2 =  simdrv_xch_apdu(reader_id, cmd_header, data_info, &result_info);

  return FKT_convert_error (sw1sw2,result_info.c_result);
}
  

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

  PURPOSE : PIN/PUK count is checked for secret code initialisation.
            count is set to zero, if not initialised, otherwise the
            initialisation flag (most significant bit) is reset.
*/

GLOBAL UBYTE FKT_check_pin_count (UBYTE count)
{
  if ((count & 0x80) EQ 0)
    return 0;

  return count & 0x0F;
}

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

  PURPOSE : Converts sw1 and sw2 to an unique error code for the
            SIM application.

*/

/*
 * PIN/PUK is wrong, remaining attempts
 */
static const  USHORT sim_inv_chv_A [6] =
{
    /* last requested PIN no          error code  */
    /* none                  */       SIM_CAUSE_OTHER_ERROR,
    /* PIN 1                 */       SIM_CAUSE_PIN1_EXPECT,
    /* PIN 2                 */       SIM_CAUSE_PIN2_EXPECT,
    /* PUK 1                 */       SIM_CAUSE_PUK1_EXPECT,
    /* PUK 2                 */       SIM_CAUSE_PUK2_EXPECT,
    /* NEVER                 */       SIM_CAUSE_ACCESS_PROHIBIT
};


/*
 * PIN/PUK is wrong, no remaining attempts
 */
static const  USHORT sim_inv_chv_B [6] =
{
    /* last requested PIN no          error code  */
    /* none                  */       SIM_CAUSE_OTHER_ERROR,
    /* PIN 1                 */       SIM_CAUSE_PIN1_BLOCKED,
    /* PIN 2                 */       SIM_CAUSE_PIN2_BLOCKED,
    /* PUK 1                 */       SIM_CAUSE_PUK1_BLOCKED,
    /* PUK 2                 */       SIM_CAUSE_PUK2_BLOCKED,
    /* NEVER                 */       SIM_CAUSE_OTHER_ERROR
};

GLOBAL USHORT FKT_convert_error (USHORT sw1sw2, USHORT size)
{
  TRACE_FUNCTION ("FKT_convert_error()");

  sim_data.sw1 = (UBYTE)(sw1sw2 >> 8);
  sim_data.sw2 = (UBYTE)sw1sw2;

  TRACE_EVENT_P1 ("Data returned from SIM, Size =%X", size);
  TRACE_EVENT_P2 ("SW1=%02X SW2=%02X", sim_data.sw1, sim_data.sw2);

  switch (sim_data.sw1)
  {
    case 0x00:
      /*
       * SIM driver error
       */
      if (SIM_IS_FLAG_CLEARED(SIM_INSERT))
      {
        return SIM_CAUSE_CARD_REMOVED;
      }
      if (sim_data.sw2 EQ 14)
      {
        SIM_SET_FLAG(DRV_FAILED_RETRY);
        return SIM_CAUSE_DRV_TEMPFAIL;
      }
      return CAUSE_MAKE(DEFBY_CONDAT, ORIGSIDE_MS, SIM_ORIGINATING_ENTITY, sim_data.sw2);
#if defined SIM_TOOLKIT
    case 0x9E:
      /*
       * use SW2 as length indicator for
       * the following get response
       */
      if (sim_data.sim_phase >= 3)  /* Phase 2+ or higher */
      {
        if (sim_data.stk_profile[0] & SAT_TP1_9E_XX)
        {
          sim_data.sim_data_len = (sim_data.sw2 EQ 0)? 0x100: (USHORT)sim_data.sw2;
          return SIM_CAUSE_DNL_ERROR;
        }
        else
          return SIM_CAUSE_SAT_BUSY;
      }
      else
        return SIM_CAUSE_OTHER_ERROR;
    case 0x93:
      if (sim_data.sim_phase >= 3)  /* Phase 2+ or higher */
      {
        return SIM_CAUSE_SAT_BUSY;
      }
      else
        return SIM_CAUSE_OTHER_ERROR;
    case 0x91:
      if (sim_data.sim_phase >= 3)  /* Phase 2+ or higher */
      {
        sim_data.proactive_sim_data_len = (sim_data.sw2 EQ 0)? 0x100: (SHORT)sim_data.sw2;
        return SIM_NO_ERROR;
      }
      else
        return SIM_CAUSE_OTHER_ERROR;
#endif
    case 0x92:
      if (sim_data.sw2 > 0xF)
      {
#ifdef REL99
        if (sim_data.sw2 EQ SW2_MEMORY_PROBLEM)
        {
          return SIM_CAUSE_MEM_PROBLEM;
        }
#endif /* end of ifdef REL99 */
        return SIM_CAUSE_OTHER_ERROR;
      }
      /* no break (otherwise the command was successful)*/
    case 0x90:
      if( (size>0) AND (size <= 0x100) )
      {
        sim_data.sim_data_len = size;
        TRACE_EVENT_P1 ("sim_data.sim_data_len updated size =%X ", size);
      }
      return SIM_NO_ERROR;
    case 0x9F:
      /*
       * use SW2 as length indicator for
       * the following get response
       */
      sim_data.sim_data_len = (sim_data.sw2 EQ 0)? 0x100: (USHORT)sim_data.sw2;
      return SIM_NO_ERROR;

    case 0x94:
      switch (sim_data.sw2)
      {
        case 0:
          return SIM_CAUSE_NO_SELECT;
        case 2:
          return SIM_CAUSE_ADDR_WRONG;
        case 4:
          return SIM_CAUSE_UNKN_FILE_ID;
        case 8:
          return SIM_CAUSE_CMD_INCONSIST;
        default:
          break;
      }
      break;

    case 0x98:
      TRACE_EVENT_P1 ("LRP = %d", (int)sim_data.last_requested_pin_no);

      switch (sim_data.sw2)
      {
        case 2:
          return SIM_CAUSE_CHV_NOTSET;
        case 8:
          return SIM_CAUSE_CHV_VALIDATED;
        case 0x10:
          return SIM_CAUSE_EF_INVALID;    /* contradiction cases */
        case 4:
//TISH, patch for OMAPS00115342&OMAPS00123717
//start
#if 0        	
          /* Check whether PIN1 is entered/Verified */
          if (SIM_IS_FLAG_SET(PIN1_VERIFIED))
            return SIM_CAUSE_ACCESS_PROHIBIT;
          else
#endif
//end          	
            return sim_inv_chv_A [sim_data.last_requested_pin_no];
        case 0x40:
          return sim_inv_chv_B [sim_data.last_requested_pin_no];
        case 0x50:
          return SIM_CAUSE_MAX_INCREASE;
        default:
          break;
      }
      break;
  }

  return SIM_CAUSE_OTHER_ERROR;
}

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

  PURPOSE : Wrapping function for the SIM driver call SIM_ChangeCHV.

*/

GLOBAL USHORT FKT_ChangeCHV (UBYTE      * old_pin,
                             UBYTE      * new_pin,
                             UBYTE        pin_id)
{
/* Implements Measure# 13 */
  return (FKT_ChangeCHV_n_UnblockCHV (old_pin, new_pin, pin_id, SIMDRV_INS_CHANGE_CHV)); 
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_DisableCHV.

*/

GLOBAL USHORT FKT_DisableCHV (UBYTE      * pin)
{
/* Implements Measure# 17 */
  return (FKT_DisableCHV_n_EnableCHV (pin, SIMDRV_INS_DISABLE_CHV)); 
}

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

  PURPOSE : Wrapping function for the SIM driver call SIM_EnableCHV.

*/

GLOBAL USHORT FKT_EnableCHV (UBYTE      * pin)
{ 
/* Implements Measure# 17 */
  return (FKT_DisableCHV_n_EnableCHV (pin, SIMDRV_INS_ENABLE_CHV)); 
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_Increase.

*/

GLOBAL USHORT FKT_Increase (UBYTE * data)
{
    USHORT sw1sw2;
    USHORT size = 0;
    U8           reader_id;
    T_SIMDRV_cmd_header       cmd_header;
    T_SIMDRV_data_info   data_info;
    T_SIMDRV_result_info  result_info;
    UBYTE response[SIMDRV_MAX_RESULT];
    
    TRACE_FUNCTION ("FKT_Increase()");
   reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
   cmd_header.cla = SIMDRV_GSM_CLASS_BYTE ;
   cmd_header.ins = SIMDRV_INS_INCREASE;
   cmd_header.p1 = 0;
   cmd_header.p2 = 0;
   
   data_info.data  = (U8 *)data;
   data_info.c_data =  3;
   
   result_info.result = response;
   result_info.c_result = size;
   result_info.len  = NOT_PRESENT_16BIT;
  
   sw1sw2 = simdrv_xch_apdu(reader_id,cmd_header,data_info,&result_info);
  return FKT_convert_error (sw1sw2,result_info.c_result);
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_Invalidate.

*/

GLOBAL USHORT FKT_Invalidate (void)
{
/* Implements Measure# 16 */
    return (FKT_Invalidate_n_Rehabilitate(SIMDRV_INS_INVALIDATE));
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_ReadBinary.

*/

GLOBAL USHORT FKT_ReadBinary (UBYTE      * data,
                              USHORT       offset,
                              USHORT       length)
{
  USHORT sw1sw2;
  USHORT size = 0;
    U8           reader_id;
    T_SIMDRV_cmd_header       cmd_header;
    T_SIMDRV_data_info   data_info;
    T_SIMDRV_result_info  result_info;
    U8 offset_high;
    U8 offset_low;
    
    TRACE_FUNCTION ("FKT_ReadBinary()");
  offset_high = (U8)((offset &0x7F00)>>8); /* to make the 8th bit 0 as per 102.221 */ 
  offset_low = (U8)(offset & 0x00FF); 
  
  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = SIMDRV_INS_READ_BINARY;
  cmd_header.p1 =offset_high ;
  cmd_header.p2 =offset_low ;
  
  data_info.data   = NULL;
  data_info.c_data = 0;
  
  result_info.result    = (U8 *)data;
  result_info.c_result = size;
  result_info.len  = (USHORT)length;
  
   sw1sw2= simdrv_xch_apdu (reader_id,cmd_header,data_info,&result_info);
  return FKT_convert_error (sw1sw2,result_info.c_result);
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_ReadRecord.

*/

GLOBAL USHORT FKT_ReadRecord (UBYTE      * data,
                              UBYTE        mode,
                              USHORT       record,
                              USHORT       length)
{
  USHORT sw1sw2;
  USHORT size = 0;
    U8           reader_id;
    T_SIMDRV_cmd_header       cmd_header;
    T_SIMDRV_data_info   data_info;
    T_SIMDRV_result_info  result_info;
    
#if !defined NTRACE
/* Implements Measure#32: Row 37 */
  TRACE_EVENT_P1("FKT_ReadRecord(): Nr. %hu", record);
#endif
  
  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = SIMDRV_INS_READ_RECORD;
  cmd_header.p1 = (U8)record;
  cmd_header.p2 = (U8)mode;
  
  data_info.data   = NULL;
  data_info.c_data = 0;
  
  result_info.result   = (U8 *)data ;
  result_info.c_result = size;
  result_info.len  =(USHORT)length;
  
   sw1sw2= simdrv_xch_apdu (reader_id,cmd_header,data_info,&result_info);
  return FKT_convert_error (sw1sw2,result_info.c_result);
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_Rehabilitate.

*/

GLOBAL USHORT FKT_Rehabilitate (void)
{
/* Implements Measure# 16 */
    return (FKT_Invalidate_n_Rehabilitate(SIMDRV_INS_REHABILITATE));
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_Status.

*/

GLOBAL USHORT FKT_Status (UBYTE * pin_cnt,
                          UBYTE * pin2_cnt,
                          UBYTE * puk_cnt,
                          UBYTE * puk2_cnt)
{
  USHORT size = 0;
  USHORT sw1sw2; 
  U8  reader_id;
  T_SIMDRV_cmd_header  cmd_header;
  T_SIMDRV_data_info  data_info;
  T_SIMDRV_result_info    result_info;
 
 USHORT cause;
 USHORT fileid;
 union
 {
   T_DIR_STATUS status;
   UBYTE response [40];
 } dir;

  TRACE_FUNCTION ("FKT_Status()");

  memset (dir.response, 0, sizeof(dir.response));
  
  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;

  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = SIMDRV_INS_STATUS;
  cmd_header.p1 = 0;
  cmd_header.p2 = 0;
  
  data_info.data   = NULL;
  data_info.c_data = 0;

  result_info.result = (U8 *)dir.response;
  result_info.c_result = size;
  result_info.len = sim_data.dir_status_len;

  sw1sw2 =  simdrv_xch_apdu(reader_id, cmd_header, data_info, &result_info);
  
  cause =  FKT_convert_error (sw1sw2,result_info.c_result);
  
  *pin_cnt  = 0;
  *puk_cnt  = 0;
  *pin2_cnt = 0;
  *puk2_cnt = 0;

  if (cause EQ SIM_NO_ERROR)
  {
    /*
     * Check file id on active call: if different from last directory
     * indicate failure during SIM Presence Detection (27.20).
     * A selection of a non-existent DF (possible with SIM_ACCESS_REQ)
     * leads to the loss of the current DF: this confuses the SIM
     * Presence Detection, therefore the validity of the actual DF
     * stored in 'sim_data.act_directory' must be considered.
     */
    fileid = (dir.status.fileid[0] << 8) | dir.status.fileid[1];

    if (SIM_IS_FLAG_SET (CALL_ACTIVE) AND             /* call active */
        sim_data.act_directory NEQ NOT_PRESENT_16BIT  /* actual DF known? */
        AND fileid NEQ sim_data.act_directory)        /* compare DF */
      return SIM_CAUSE_CARD_REMOVED;
    else
    {
      if (SIM_TI_DRV_X_BYTES > 0)   /* discard SW1, SW2 from response! */
        memset (&dir.response[sim_data.dir_status_len], 0, SIM_TI_DRV_X_BYTES);
      /*
       * Directory status is available
       */
      *pin_cnt  = FKT_check_pin_count (dir.status.pinstatus);
      *puk_cnt  = FKT_check_pin_count (dir.status.unbstatus);
      *pin2_cnt = FKT_check_pin_count (dir.status.pin2status);
      *puk2_cnt = FKT_check_pin_count (dir.status.unb2status);
    }
  }
  return cause;
}

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

  PURPOSE : Wrapping function for the SIM driver call SIM_RunGSMAlgo.

*/

GLOBAL USHORT FKT_RunGSMAlgo           (UBYTE      * rand, UBYTE      * data, USHORT       len)
{
  USHORT sw1sw2;
  USHORT size = 0;
    U8           reader_id;
    T_SIMDRV_cmd_header       cmd_header;
    T_SIMDRV_data_info   data_info;
    T_SIMDRV_result_info  result_info;
  
    TRACE_FUNCTION ("FKT_RunGSMAlgo()");
  
  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE ;
  cmd_header.ins = SIMDRV_INS_AUTHENTICATE;
  cmd_header.p1 = 0;
  cmd_header.p2 = 0;
  
  data_info.data   = (U8*)rand;
  data_info.c_data = MAX_RAND;
  
  result_info.result = data;
  result_info.c_result = size;
  result_info.len  = len;
  
  sw1sw2= simdrv_xch_apdu (reader_id,cmd_header,data_info,&result_info);

  return FKT_convert_error (sw1sw2,result_info.c_result);
  }


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

  PURPOSE : Wrapping function for the SIM driver call SIM_Select.

*/
LOCAL USHORT fkt_select_one (USHORT id, UBYTE      * data, USHORT       len)
{

  USHORT size = 0;
  USHORT sw1sw2;
  U8  reader_id;
  T_SIMDRV_cmd_header  cmd_header;
  U8  field[2];
  T_SIMDRV_data_info  data_info;
  T_SIMDRV_result_info    result_info;

  TRACE_EVENT_P1 ("fkt_select_one() : File id =%X ", id);

  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;

  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = SIMDRV_INS_SELECT;
  cmd_header.p1 = 0;
  cmd_header.p2 = 0;

  field[0] =(U8) (id>>8);  /* high byte */
  field[1] =(U8) id;       /* low byte */
  
  data_info.data = field;
  data_info.c_data = sizeof(field);
  
  result_info.result = data;
  result_info.c_result = size;
  result_info.len = len;

  TRACE_EVENT_P1 ("Expected result size from SIM =%X ", result_info.len);

  sw1sw2 =  simdrv_xch_apdu(reader_id, cmd_header, data_info, &result_info);  
  
  return FKT_convert_error (sw1sw2,result_info.c_result);
  }

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

  PURPOSE : Function to select the directory given the path.

*/
LOCAL USHORT sim_select_df(U16 dir_level,UBYTE *data,USHORT len)
{
  USHORT result = SIM_NO_ERROR;

  result = fkt_select_one (dir_level, data, len);
  if (result NEQ SIM_NO_ERROR)
  {
     sim_data.act_directory = NOT_PRESENT_16BIT;
     sim_data.act_field     = NOT_PRESENT_16BIT;
  }
  else
  {
     sim_data.act_directory = dir_level;
  }
  return result;
}

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

  PURPOSE : Wrapping function for the SIM driver call SIM_Select.

*/
GLOBAL USHORT FKT_Select (USHORT       id,
                          BOOL         path_info_present, T_path_info * path_info_ptr,
                          UBYTE      * data, USHORT  len)
{
  USHORT result;
  USHORT directory = (SIM_IS_FLAG_SET (GSM_DATAFIELD))?
                     SIM_DF_GSM: SIM_DF_1800;   /* default parent directory */

#if !defined NTRACE
/* Implements Measure#32: Row 39 */
  TRACE_EVENT_P1("FKT_Select(): id = %04X", id);
#endif
  switch (id & 0xFF00)  /* selecting DF deselects EF */
  {
  case 0x3F00:
  case 0x7F00:
  case 0x5F00:
    sim_data.act_field = NOT_PRESENT_16BIT;
    break;
  }

  if( path_info_present NEQ FALSE )
  {
    if((sim_data.act_directory & 0xFF00) NEQ 0x5F00 AND 
        sim_data.act_directory NEQ NOT_PRESENT_16BIT)
    {
      /* Currently selected df is MF or a first level directory */
      if(sim_data.act_directory NEQ path_info_ptr->df_level1)
      {
        result = sim_select_df(path_info_ptr->df_level1,data,len);
        if(result NEQ SIM_NO_ERROR)
          return result;
      }
    }
    /* Currently selected df is a second level directory */
    else
    {
      result = sim_select_df(SIM_MF,data,len);
      if(result NEQ SIM_NO_ERROR)
        return result;
      result = sim_select_df(path_info_ptr->df_level1,data,len);
      if(result NEQ SIM_NO_ERROR)
        return result;
    }
    if(path_info_ptr->v_df_level2)
    {
      result = sim_select_df(path_info_ptr->df_level2,data,len);
      if(result NEQ SIM_NO_ERROR)
        return result;
    }
    result = fkt_select_one (id, data, len);
    if (result NEQ SIM_NO_ERROR)
    {
      sim_data.act_field = NOT_PRESENT_16BIT;
    }
    else
    {
      sim_data.act_field = id;
    }
    return result;
  }
  else
  {
  switch (id)
  {
  case SIM_MF:
    result = fkt_select_one (SIM_MF, data, len);
    if (result NEQ SIM_NO_ERROR)
      sim_data.act_directory = NOT_PRESENT_16BIT;
    else
    {
      sim_data.dir_status_len = sim_data.sim_data_len;
      sim_data.act_directory = id;
    }
    return result;

  default:
          /* All the standard defined EFs would be handled before coming to this
           * point. Complete path information should be given for non-standard 2nd level EFs 
           * and they also would be handled before coming to this point.
           * This statement will be hit for non-standard files 
           * without path information. Hence returning error */
          return SIM_CAUSE_UNKN_FILE_ID;

      /* continue here in case of any first level directory */
  case SIM_DF_GSM:
  case SIM_DF_1800:
  case SIM_DF_TELECOM:
  case SIM_DF_VI:
    if (sim_data.act_directory EQ id)
      return SIM_NO_ERROR;  /* already selected */
    else
    {
          /* If current directory has not been selected or it is a 
             2nd level and under another 1st level DF */        
          if (((sim_data.act_directory & 0xFF00) EQ 0x5F00 AND
               ! SIM_IS_DF_LEVEL2_UNDER_DF_LEVEL1(sim_data.act_directory,id))
               OR sim_data.act_directory EQ NOT_PRESENT_16BIT)
      {                     /* MF has to be selected first */
           result = sim_select_df(SIM_MF,data,len);
           if(result NEQ SIM_NO_ERROR)
             return result;
      }
       result = fkt_select_one (id, data, len);
      if (result NEQ SIM_NO_ERROR)
      {
        sim_data.act_directory = NOT_PRESENT_16BIT;
        sim_data.act_field = NOT_PRESENT_16BIT;
      }
      else
      {
        sim_data.dir_status_len = sim_data.sim_data_len;
        sim_data.act_directory = id;
      }
      return result;
    }
  case SIM_DF_GRAPHICS:
    directory = SIM_DF_TELECOM;   /* parent directory */
    /* no break */
    /*lint -fallthrough*/
  case SIM_DF_SOLSA:
      case SIM_DF_MEXE:
    if (sim_data.act_directory EQ id)
      return SIM_NO_ERROR;  /* already selected */

    if (sim_data.act_directory NEQ directory)
    {                       /* not the parent directory */
          /* If current directory is MF or first level OR if the 2nd level 
           directory is under another 1st level df, select the parent directory */
          if((sim_data.act_directory & 0xFF00) NEQ 0x5F00 ||
             (!SIM_IS_DF_LEVEL2_UNDER_DF_LEVEL1(sim_data.act_directory,directory)) )
        {
            result = FKT_Select (directory, FALSE, NULL, data, len);
            if (result NEQ SIM_NO_ERROR)
            {
              sim_data.act_directory = NOT_PRESENT_16BIT;
              return result;
            }
      }
    }
    result = fkt_select_one (id, data, len);
    if (result NEQ SIM_NO_ERROR)
    {
      sim_data.act_directory = NOT_PRESENT_16BIT;
      sim_data.act_field = NOT_PRESENT_16BIT;
    }
    else
    {
      sim_data.dir_status_len = sim_data.sim_data_len;
      sim_data.act_directory = id;
    }
    return result;

  case SIM_ICCID:
  case SIM_ELP:
    /*
     * Access to Root Directory
     */
    directory = SIM_MF;
    break;

  case SIM_ADN:
  case SIM_FDN:
  case SIM_SMS:
  case SIM_CCP:
  case SIM_MSISDN:
  case SIM_SMSP:
  case SIM_SMSS:
  case SIM_LND:
  case SIM_SMSR:
  case SIM_SDN:
  case SIM_EXT1:
  case SIM_EXT2:
  case SIM_EXT3:
  case SIM_BDN:
  case SIM_EXT4:
/* VO temp PATCH: Needed for reading CPHS info num from old SIMs */
  case SIM_CPHS_INFN2:
/* VO temp PATCH end */
    /*
     * Access to Telecom Directory
     */
    directory = SIM_DF_TELECOM;
    break;

      case SIM_LP:
      case SIM_IMSI:
      case SIM_KC:
      case SIM_PLMNSEL:
      case SIM_HPLMN:
      case SIM_ACMMAX:
      case SIM_SST:
      case SIM_ACM:
      case SIM_GID1:
      case SIM_GID2:
      case SIM_PUCT:
      case SIM_CBMI:
      case SIM_SPN:
      case SIM_CBMID:
      case SIM_BCCH:
      case SIM_ACC:
      case SIM_FPLMN:
      case SIM_LOCI:
      case SIM_AD:
      case SIM_PHASE:
      case SIM_VGCS:
      case SIM_VGCSS:
      case SIM_VBS:
      case SIM_VBSS:
      case SIM_EMLPP:
      case SIM_AAEM:
      case SIM_ECC:
      case SIM_CBMIR:
      case SIM_DCK:
      case SIM_CNL:
      case SIM_NIA:
      case SIM_KCGPRS:
      case SIM_LOCGPRS:
      case SIM_SUME:
      case SIM_CPHS_VMW:
      case SIM_CPHS_SST:
      case SIM_CPHS_CFF:
      case SIM_CPHS_ONSTR:
      case SIM_CPHS_CSP:
      case SIM_CPHS_CINF:
      case SIM_CPHS_MBXN:
      case SIM_CPHS_ONSHF:
      case SIM_CPHS_INFN:
#ifdef REL99
      case SIM_UCPS_ACTEC:
      case SIM_OCPS_ACTEC:
      case SIM_HPLMN_ACT:
      case SIM_CPBCCH:
      case SIM_INV_SCAN:
      case SIM_RPLMN_ACT:
#endif
      case SIM_PNN:
      case SIM_OPL:
        
        /*
         * Access to GSM
         */
        directory = (SIM_IS_FLAG_SET (GSM_DATAFIELD))?
                     SIM_DF_GSM: SIM_DF_1800;
        break;

      case SIM_MEXE_ST:
      case SIM_ORPK:
      case SIM_ARPK:
      case SIM_TPRPK:
        /*
         * Access to MExE Directory
         */
        directory = SIM_DF_MEXE;
        break;
  case SIM_IMG:
    /*
     * Access to Icon Directory
     */
    directory = SIM_DF_GRAPHICS;
    break;

  case SIM_SAI:
  case SIM_SLL:
    /*
     * Access to SoLSA Directory
     */
    directory = SIM_DF_SOLSA;
    break;
    }
  }

  if (sim_data.act_directory NEQ directory)
  {
    /*
     * select directory
     */
      result = FKT_Select (directory, FALSE, NULL, data, len);
      if (result NEQ SIM_NO_ERROR)    /* directory selection fails */
      {
        sim_data.act_directory = NOT_PRESENT_16BIT;
        sim_data.act_field = NOT_PRESENT_16BIT;
        return result;
      }
  }

  if (sim_data.act_field NEQ id)
  {
    /*
     * secondly select elementary field
     */
     result = fkt_select_one (id, data, len);
    if (result NEQ SIM_NO_ERROR)    /* EF selection fails */
    {
      sim_data.act_field = NOT_PRESENT_16BIT;
#ifdef __INVALID    /* more sophisticated SELECT error handling */

      sw1 = (UBYTE)(SIM_Status_Extended ((UBYTE *)response, 6, &size) >> 8);

      if (sw1 NEQ 0x90 AND sw1 NEQ 0x91)
        /*
         * SIM Status request failed
         */
        sim_data.act_directory = NOT_PRESENT_16BIT;
      else if (((response[4] << 8) | response[5])
                NEQ sim_data.act_directory)
        /*
         * SIM Presence Detection indicates invalid SIM
         */
        sim_data.act_directory = NOT_PRESENT_16BIT;
#endif
    }
    else
    {
      sim_data.act_directory = directory;
      sim_data.act_field = id;
    }
    return result;
  }
  else
    /*
     * field is already selected
     */
    return SIM_NO_ERR_FILE_ALREADY_SELECTED;
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_UnblockCHV.

*/

GLOBAL USHORT FKT_UnblockCHV (UBYTE      * unblockCHV,
                              UBYTE      * new_CHV,
                              UBYTE        chvType)
{
/* Implements Measure# 13 */
  return (FKT_ChangeCHV_n_UnblockCHV (unblockCHV, new_CHV, chvType, SIMDRV_INS_UNBLOCK_CHV)); 
  }


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

  PURPOSE : Wrapping function for the SIM driver call SIM_UpdateBinary.

*/

GLOBAL USHORT FKT_UpdateBinary (UBYTE      * data,
                                USHORT       length,
                                USHORT       offset)
{
    USHORT size = 0;
    USHORT sw1sw2;
    U8           reader_id;
    T_SIMDRV_cmd_header       cmd_header;
    T_SIMDRV_data_info   data_info;
    T_SIMDRV_result_info  result_info;
    U8 offset_high;
    U8 offset_low;
    UBYTE response[SIMDRV_MAX_RESULT];
  
    TRACE_FUNCTION ("FKT_UpdateBinary()");
    
  offset_high = (U8)((offset &0x7F00)>>8);/*to make the 8th bit 0 as per 102.221*/
  offset_low = (U8)(offset & 0x00FF);
  
  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE ;
  cmd_header.ins = SIMDRV_INS_UPDATE_BINARY;
  cmd_header.p1 = offset_high;
  cmd_header.p2 = offset_low;
  
  data_info.data   = (U8 *)data;
  data_info.c_data = (U8)length;
  
  result_info.result = response;
  result_info.c_result = size;
  result_info.len  = NOT_PRESENT_16BIT;
  
  sw1sw2= simdrv_xch_apdu (reader_id,cmd_header,data_info,&result_info);
  return FKT_convert_error (sw1sw2,result_info.c_result);
  }


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

  PURPOSE : Wrapping function for the SIM driver call SIM_UpdateRecord.

*/

GLOBAL USHORT FKT_UpdateRecord (UBYTE      * data,
                                USHORT       length,
                                UBYTE        mode,
                                USHORT       record)
{
    USHORT size = 0;
    USHORT sw1sw2;
    U8           reader_id;
    T_SIMDRV_cmd_header       cmd_header;
    T_SIMDRV_data_info   data_info;
    T_SIMDRV_result_info  result_info;
    UBYTE response[SIMDRV_MAX_RESULT];
  
#if !defined NTRACE
/* Implements Measure#32: Row 40 */
    TRACE_EVENT_P1("FKT_UpdateRecord(): Nr. %hu", record);
#endif
  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE ;
  cmd_header.ins = SIMDRV_INS_UPDATE_RECORD;
  cmd_header.p1 = (U8)record;
  cmd_header.p2 = (U8)mode;
  
  data_info.data   = (U8*)data;
  data_info.c_data = (U8)length;
  
  result_info.result = response;
  result_info.c_result = size;
  result_info.len  = NOT_PRESENT_16BIT;
  
   sw1sw2= simdrv_xch_apdu (reader_id,cmd_header,data_info,&result_info);
  return FKT_convert_error (sw1sw2,result_info.c_result);
  }



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

  PURPOSE : Wrapping function for the SIM driver call SIM_VerifyCHV.

*/

GLOBAL USHORT FKT_VerifyCHV (UBYTE      * pin,
                             UBYTE        pin_id)
{
  USHORT size = 0;
  USHORT sw1sw2;
  U8  reader_id;
  T_SIMDRV_cmd_header  cmd_header;
  T_SIMDRV_data_info  data_info;
  T_SIMDRV_result_info    result_info;
  UBYTE response[SIMDRV_MAX_RESULT];

  TRACE_FUNCTION ("FKT_VerifyCHV()");

  reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;

  cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
  cmd_header.ins = SIMDRV_INS_VERIFY_CHV;
  cmd_header.p1 = 0x00;
  cmd_header.p2 = pin_id;

  data_info.data = (U8 *)pin;
  data_info.c_data = MAX_PIN_LEN;
  
  result_info.result = response;
  result_info.c_result = size;
  result_info.len = NOT_PRESENT_16BIT;

  sw1sw2 =  simdrv_xch_apdu(reader_id, cmd_header, data_info, &result_info);

  return FKT_convert_error (sw1sw2,result_info.c_result);
  }

/*
+********************************************************************+
| Moved from sim_stk.c - for CQ 34109 under feature flag SIM_TOOLKIT |
+********************************************************************+
*/

#ifdef SIM_TOOLKIT

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

  PURPOSE : Wrapping function for the SIM driver call SIM_TerminalResponse

*/

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
};

UBYTE pending_timers[9] = {0,0,0,0,0,0,0,0,0};
UBYTE next_pos_to_fill = 0;
UBYTE next_pos_to_send = 0;

GLOBAL USHORT FKT_TerminalResponse (UBYTE * data,
                                    USHORT  length)
{
      USHORT size = 0;
      USHORT sw1sw2;
      U8 reader_id;
      T_SIMDRV_cmd_header cmd_header;
      T_SIMDRV_data_info data_info;
      T_SIMDRV_result_info result_info;
      UBYTE response[SIMDRV_MAX_RESULT];
      UBYTE env[sizeof(timer_env)];
      USHORT index;
      UBYTE dummy[4];
      USHORT error;
      USHORT i;

      TRACE_FUNCTION ("FKT_TerminalResponse()");

      reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
      cmd_header.cla = SIMDRV_GSM_CLASS_BYTE ;
      cmd_header.ins = SIMDRV_INS_TERMINAL_RESPONSE;
      cmd_header.p1 = 0;
      cmd_header.p2 = 0;
    
      data_info.data = data;
      data_info.c_data = (U8)length;
    
      result_info.result = response;
      result_info.c_result = size;
      result_info.len = NOT_PRESENT_16BIT;

      sw1sw2 = simdrv_xch_apdu(reader_id,cmd_header,data_info,&result_info);

      sim_data.term_resp_sent = TRUE;

      SIM_EM_TERMINAL_RESPONSE;
      /*
      * if SIM response is OK, try resending pending timer expiry envelopes (send updated envelopes)
      */
     if( 0x9000 == sw1sw2 )
     { 
       for(i=0;i<8;i++)
       { 
         if (next_pos_to_fill != next_pos_to_send)
         { 
           /*
           * some timer expiry envelopes are pending
           */
           index = pending_timers[next_pos_to_send];
           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);
           if(8 == next_pos_to_send)
           {
             next_pos_to_send = 0;
           }
           else
           {
             next_pos_to_send++;
           }
           if (error NEQ SIM_NO_ERROR)
           {
             break;
           }
         } 
       } 
     } 

  return FKT_convert_error (sw1sw2,result_info.c_result);

}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_Envelope

*/

GLOBAL USHORT FKT_Envelope  (UBYTE      * data_out, UBYTE      * data_in,
                             USHORT       in_length, USHORT       out_length)
{

     USHORT    size = 0;
     USHORT    sw1sw2;
     USHORT    error;
      U8 reader_id;
      T_SIMDRV_cmd_header cmd_header;
      T_SIMDRV_data_info data_info;
      T_SIMDRV_result_info result_info;

     TRACE_FUNCTION ("FKT_Envelope()");
  
     reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
 
     cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
     cmd_header.ins = SIMDRV_INS_ENVELOPE;
     cmd_header.p1 = 0;
     cmd_header.p2 = 0;
 
     data_info.data = data_in;
     data_info.c_data = (U8)in_length;

     result_info.result = data_out;
     result_info.c_result = size;
     result_info.len = out_length;
 
     sw1sw2 = simdrv_xch_apdu(reader_id,cmd_header,data_info,&result_info);

  SIM_EM_ENVELOPE;

  sim_data.sim_data_len = 0;
  TRACE_EVENT("sim_data.sim_data_len initialised as 0"); /* for debug only - to be removed */

  error = FKT_convert_error (sw1sw2,result_info.c_result);

  stk_l_cmd = sim_data.sim_data_len << 3;

  return error;
  
 }

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

  PURPOSE : Wrapping function for the SIM driver call SIM_TerminalProfile

*/

GLOBAL USHORT FKT_TerminalProfile (UBYTE * data,
                                   USHORT  length)
{
      USHORT    size = 0;
      USHORT    sw1sw2;
      U8 reader_id;
      T_SIMDRV_cmd_header cmd_header;
      T_SIMDRV_data_info data_info;
      T_SIMDRV_result_info result_info;
      UBYTE response[SIMDRV_MAX_RESULT];

      TRACE_FUNCTION ("FKT_TerminalProfile()");

      reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
      cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
      cmd_header.ins = SIMDRV_INS_TERMINAL_PROFILE;
      cmd_header.p1 = 0;
      cmd_header.p2 = 0;
    
      data_info.data = data;
      data_info.c_data = (U8)length;
    
      result_info.result = response;
      result_info.c_result = size;
      result_info.len = NOT_PRESENT_16BIT;

      sw1sw2= simdrv_xch_apdu(reader_id,cmd_header,data_info,&result_info);

  return FKT_convert_error (sw1sw2,result_info.c_result);
  
}


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

  PURPOSE : Wrapping function for the SIM driver call SIM_Fetch

*/

GLOBAL USHORT FKT_Fetch (UBYTE * cmd,
                         USHORT  length)
{
     USHORT    size = 0;
     USHORT    sw1sw2;
      U8 reader_id;
      T_SIMDRV_cmd_header cmd_header;
      T_SIMDRV_data_info data_info;
      T_SIMDRV_result_info result_info;

     TRACE_FUNCTION ("FKT_Fetch()");

     reader_id = SIMDRV_VAL_READER_ID__RANGE_MIN;
     cmd_header.cla = SIMDRV_GSM_CLASS_BYTE;
     cmd_header.ins = SIMDRV_INS_FETCH;
     cmd_header.p1 = 0;
     cmd_header.p2 = 0;

     data_info.data = NULL;
     data_info.c_data = 0;

     result_info.result = cmd;
     result_info.c_result = size;
     result_info.len = (USHORT)length;

     sw1sw2 = simdrv_xch_apdu(reader_id,cmd_header,data_info,&result_info);
  
  return FKT_convert_error (sw1sw2,result_info.c_result);
  
}

#endif /* SIM_TOOLKIT */

#endif