view src/aci2/mfw/mfw_sim.~c @ 597:f18b29e27be5

First attempt at MCSI voice path automatic switching The function is implemented at the ACI level in both aci2 and aci3, successfully avoids triggering the DSP bug on the first call, but the shutdown of MCSI upon call completion is not working properly yet in either version.
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 27 Mar 2019 22:18:35 +0000
parents 93999a60b835
children
line wrap: on
line source

/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417)         $Workfile:: mfw_sim.c       $|
| $Author:: Vo                          $Revision::  1              $|
| CREATED: 13.10.98                     $Modtime:: 22.03.00 17:21   $|
| STATE  : code                                                      |
+--------------------------------------------------------------------+

   MODULE  : MFW_SIM

   PURPOSE : This modul contains the functions for SIM management.


   $History:: mfw_sim.c                                              $
 *
 * *****************  Version 43  *****************
 * User: Vo           Date: 22.03.00   Time: 17:29
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * Add new parameter PIN type in structure T_MFW_SIM_STATUS to
 * identify PIN type
 * Change in SIM lock
 *
 * *****************  Version 42  *****************
 * User: Es           Date: 2.03.00    Time: 16:18
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * use 'aci_delete()' instead of 'aci_ext_init()' to clear the
 * primitive routing for mfw_sim. (because other routings may have to
 * be preserved!)
 *
 * *****************  Version 41  *****************
 * User: Vo           Date: 22.12.99   Time: 16:03
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * Remove maximum preferred PLMN records and used preferred PLMN
 * records in local memory
 *
 * *****************  Version 40  *****************
 * User: Vo           Date: 2.12.99    Time: 13:18
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * New: request of max/used perferred PLMN list
 *
 * *****************  Version 39  *****************
 * User: Vo           Date: 17.11.99   Time: 11:37
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * Bug fix: de-personalisation for SIM lock
 * New: SIM inserted
 *
 * *****************  Version 38  *****************
 * User: Vo           Date: 21.10.99   Time: 13:26
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * add response of de-registration
|
| *****************  Version 37  *****************
| User: Le           Date: 11.10.99   Time: 16:27
| Updated in $/GSM/Condat/MS/SRC/MFW
|
| *****************  Version 36  *****************
| User: Le           Date: 8.10.99    Time: 13:38
| Updated in $/GSM/Condat/MS/SRC/MFW
|
| *****************  Version 35  *****************
| User: Le           Date: 4.10.99    Time: 10:33
| Updated in $/GSM/Condat/MS/SRC/MFW
 *
 * *****************  Version 34  *****************
 * User: Es           Date: 29.09.99   Time: 11:20
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * including CFUN_OK enhancement by AK, not fully implemented
 *
 * *****************  Version 33  *****************
 * User: Es           Date: 16.09.99   Time: 16:56
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * reordered include statements due to addons in mfw_phb.h
 *
 * *****************  Version 32  *****************
 * User: Vo           Date: 13.09.99   Time: 12:05
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * change comment
 *
 * *****************  Version 31  *****************
 * User: Vo           Date: 12.09.99   Time: 15:32
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * Bug fix: change PIN
 * Bug fix/New: SIM lock
 * New: request of PIN status
 * New: save preferred language
 * New: read group identifier level 1 & 2
 *
 * *****************  Version 30  *****************
 * User: Vo           Date: 30.08.99   Time: 14:23
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * bug fix
 * new function
 *
 * *****************  Version 29  *****************
 * User: Vo           Date: 9.08.99    Time: 13:11
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * PIN/PUK count
 *
 * *****************  Version 28  *****************
 * User: Vo           Date: 26.07.99   Time: 14:34
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * Move include file mfw_cb.h
 *
 * *****************  Version 27  *****************
 * User: Vo           Date: 21.07.99   Time: 14:41
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 26  *****************
 * User: Vo           Date: 16.07.99   Time: 13:50
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 25  *****************
 * User: Vo           Date: 9.07.99    Time: 14:34
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 24  *****************
 * User: Vo           Date: 2.07.99    Time: 19:03
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 23  *****************
 * User: Vo           Date: 28.05.99   Time: 9:52
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 22  *****************
 * User: Vo           Date: 31.03.99   Time: 14:09
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 21  *****************
 * User: Es           Date: 15.03.99   Time: 18:21
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * recode
 *
 * *****************  Version 20  *****************
 * User: Vo           Date: 25.02.99   Time: 16:47
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 19  *****************
 * User: Vo           Date: 17.02.99   Time: 19:03
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 18  *****************
 * User: Vo           Date: 12.02.99   Time: 18:05
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 17  *****************
 * User: Vo           Date: 12.02.99   Time: 17:46
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 16  *****************
 * User: Vo           Date: 9.02.99    Time: 14:54
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 15  *****************
 * User: Vo           Date: 12.01.99   Time: 14:27
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 14  *****************
 * User: Es           Date: 23.12.98   Time: 15:47
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 12  *****************
 * User: Es           Date: 18.12.98   Time: 13:05
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 11  *****************
 * User: Vo           Date: 17.12.98   Time: 14:31
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 10  *****************
 * User: Es           Date: 8.12.98    Time: 16:53
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 8  *****************
 * User: Vo           Date: 24.11.98   Time: 21:40
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * first successful compilation of MFW
|
| *****************  Version 6  *****************
| User: Le           Date: 11.11.98   Time: 13:35
| Updated in $/GSM/DEV/MS/SRC/MFW
|
| *****************  Version 5  *****************
| User: Le           Date: 10.11.98   Time: 16:07
| Updated in $/GSM/DEV/MS/SRC/MFW
|
| *****************  Version 4  *****************
| User: Le           Date: 10.11.98   Time: 11:08
| Updated in $/GSM/DEV/MS/SRC/MFW
|
| *****************  Version 3  *****************
| User: Le           Date: 27.10.98   Time: 15:59
| Updated in $/GSM/DEV/MS/SRC/MFW
|
| *****************  Version 2  *****************
| User: Le           Date: 21.10.98   Time: 16:20
| Updated in $/GSM/DEV/MS/SRC/MFW
*/

#define ENTITY_MFW

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#if defined (NEW_FRAME)

#include "typedefs.h"
#include "vsi.h"
#include "pei.h"
#include "custom.h"
#include "gsm.h"

#else

#include "stddefs.h"
#include "custom.h"
#include "gsm.h"
#include "vsi.h"

#endif

#include "p_sim.h"
#include "aci_cmh.h"
#include "psa.h"
#include "psa_sim.h"
#include "pcm.h"
#include "mfw_mfw.h"
#include "mfw_nm.h"
#include "mfw_sim.h"
#include "mfw_sima.h"
#include "mfw_simi.h"
#include "mfw_nmi.h"
#include "mfw_nma.h"
#include "mfw_phb.h"
#include "mfw_cm.h"
#include "mfw_cmi.h"
#include "mfw_acie.h"
#include "mfw_sms.h"
#include "mfw_smsi.h"
#include "mfw_win.h"


#include "ksd.h"
#include "psa.h"

#if defined (FAX_AND_DATA)
#include "aci_fd.h"
#endif

#include "cmh.h"
#include "phb.h"
#include "cmh_phb.h"

#include "mfw_ss.h"
#include "mfw_ssi.h"

#ifdef SIM_TOOLKIT
#include "mfw_sat.h"
#endif

extern BOOL sima_response_cb (USHORT opc, void * data);
extern void  simDecodeIMSI (UBYTE *ci, UBYTE li, UBYTE *di);
extern UBYTE mfw_IMSI [];                  /* expanded IMSI (ASCIIZ)   */
static T_MFW_SIM_STATUS sim_status;
static T_MFW_SIM_CONFIG sim_config;
static int pin_flag;
static UBYTE pin_ident;

UBYTE sim_nlock;                          /* Network lock             */
UBYTE sim_splock;                         /* Service provider lock    */
UBYTE sim_plock;                          /* SIM lock                 */
UBYTE sim_nslock;                         /* Network SUBSET lock      */
UBYTE sim_clock;                          /* corporate lock           */
UBYTE sim_blocked;         					  		/* blocked flag			        */

static UBYTE sim_service_table [10];      /* SIM service table        */
static UBYTE sim_stat = SIM_NOT_ACTIVE;

static int simCommand (ULONG cmd, void *h); /* handle win commands      */

UBYTE pin1_set = MFW_SIM_UNKNOWN;
UBYTE pin2_set = MFW_SIM_ENABLE;

static BOOL sat_update = FALSE;

static int pSlot;                       /* primitive handler slot   */

EXTERN MfwHdr * current_mfw_elem;
#if defined (WIN32)
/*
 * Only for windows to check several SIM lock combinations
 */
UBYTE sim_lock_mode = 0;     
#endif
UBYTE sim_lock_field = NOT_PRESENT_8BIT;  /* type of sim lock field   */

static UBYTE sim_get_sim_lock      (EF_SIMLCKEXT * simlck);
static void  sim_set_sim_lock      (EF_SIMLCKEXT * simlck);
static void  sim_fill_sim_lock     (EF_SIMLCKEXT * simlck);
static void  sim_check_unblock_sim (EF_SIMLCKEXT * simlck);

#define SIMLOCK_DISABLED 0
#define SIMLOCK_ENABLED  1
#define SIMLOCK_LOCKED   2
#define SIMLOCK_BLOCKED  3

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_init           |
+--------------------------------------------------------------------+

  PURPOSE : initialize SIM manager

*/

int sim_init (void)
{
    EF_SIMLCKEXT simlck;

    TRACE_FUNCTION("sim_init()");

    /* 
     * initialise SIM lock flags        
     */
    sim_nslock  = sim_plock = sim_nlock = sim_clock = sim_splock = 0; 
    sim_blocked = FALSE;

    /*
     * Read SIM Lock Flags
     */
    if (sim_get_sim_lock (&simlck) EQ PCM_OK)
    {
      sim_plock  = (UBYTE) FldGet(simlck.locks1,plock);    
      sim_nlock  = (UBYTE) FldGet(simlck.locks1,nlock);                                                        
      sim_nslock = (UBYTE) FldGet(simlck.locks1,nslock); 
      sim_splock = (UBYTE) FldGet(simlck.locks1,splock);   
      sim_clock  = (UBYTE) FldGet(simlck.locks2,clock);   

		  if (simlck.cnt >= simlck.maxcnt)
			  sim_blocked = TRUE;
		  else
			  sim_blocked = FALSE;
    }

    pin_flag  = -1;
	  pin_ident = MFW_SIM_UNKNOWN;

    /* 
     * install prim handler     
     */
    pSlot = aci_create(sima_response_cb,NULL);
    mfwCommand[MfwTypSim] = (MfwCb) simCommand;

    return TRUE;
}


/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM             |
| STATE   : code                        ROUTINE : sim_init_sim_insert |
+---------------------------------------------------------------------+

  PURPOSE : initialize SIM manager

*/

void sim_init_sim_insert()
{
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_exit           |
+--------------------------------------------------------------------+

  PURPOSE : finalize SIM manager

*/

void sim_exit (void)
{
    TRACE_FUNCTION("sim_exit()");

    /* 
     * remove prim handler      
     */
    aci_delete(pSlot);
    sim_stat = SIM_NOT_ACTIVE;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_create         |
+--------------------------------------------------------------------+

  PURPOSE : create SIM event handler

*/

T_MFW_HND sim_create (MfwHnd hWin, MfwEvt event, MfwCb cbfunc)
{
    MfwHdr *hdr;
    T_MFW_SIM *sim_para;

    TRACE_FUNCTION("sim_create()");

    hdr = (MfwHdr *) mfwAlloc(sizeof(MfwHdr));
    sim_para = (T_MFW_SIM *) mfwAlloc(sizeof(T_MFW_SIM));

    if (!hdr || !sim_para)
        return 0;

    sim_para->emask = event;
    sim_para->handler = cbfunc;

    hdr->data = sim_para;
    hdr->type = MfwTypSim;

    return mfwInsert((MfwHdr *) hWin,hdr);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_delete         |
+--------------------------------------------------------------------+

  PURPOSE : delete SIM event handler

*/

MfwRes sim_delete (MfwHnd h)
{
    TRACE_FUNCTION("sim_delete()");

    if (!h || !((MfwHdr *) h)->data)
        return MfwResIllHnd;

    if (!mfwRemove((MfwHdr *) h))
        return MfwResIllHnd;

    mfwFree((U8 *) ((MfwHdr *) h)->data,sizeof(T_MFW_SIM));
    mfwFree((U8 *) h,sizeof(MfwHdr));

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_signal         |
+--------------------------------------------------------------------+

  PURPOSE : Send a signal

*/

void sim_signal (MfwEvt event, void *para)
{
    TRACE_FUNCTION ("sim_signal()");

  if (mfwSignallingMethod EQ 0)
  {
    if (mfwFocus)
        if (sim_sign_exec(mfwFocus,event,para))
            return;
    if (mfwRoot)
        sim_sign_exec(mfwRoot,event,para);
  }
  else
    {
      MfwHdr * h = 0;

      /*
       * Focus set, then start here
       */
      if (mfwFocus)
        h = mfwFocus;
      /*
       * Focus not set, then start root
       */
      if (!h)
        h = mfwRoot;

      /*
       * No elements available, return
       */

      while (h)


      {
        /*
         * Signal consumed, then return
         */
        if (sim_sign_exec (h, event, para))
          return;

        /*
         * All windows tried inclusive root
         */
        if (h == mfwRoot)
          return;

        /*
         * get parent window
         */
        h = mfwParent(mfwParent(h));
		if(h)
			h = ((MfwWin * )(h->data))->elems;
      }
      sim_sign_exec (mfwRoot, event, para);
    }      
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_sign_exec      |
+--------------------------------------------------------------------+

  PURPOSE : Send a signal if SIM management handler

*/

int sim_sign_exec (MfwHdr *cur_elem, MfwEvt event, T_MFW_SIM_PARA *para)
{

    TRACE_FUNCTION("sim_sign_exec()");

    while (cur_elem)
    {
        if (cur_elem->type == MfwTypSim)
        {
            T_MFW_SIM *sim_data;
            sim_data = (T_MFW_SIM *) cur_elem->data;
            if (sim_data->emask & event)
            {
                sim_data->event = event;
                switch (event)
                {
                    case E_SIM_STATUS:
                        memcpy(&sim_data->para.status,
                                para,sizeof(T_MFW_SIM_STATUS));
                        break;
                }
                if (sim_data->handler)
                {
                  // PATCH LE 06.06.00
                  // store current mfw elem
                  current_mfw_elem = cur_elem;
                  // END PATCH LE 06.06.00
                  if ((*(sim_data->handler))(sim_data->event,
                                             (void *) &sim_data->para))
                    return TRUE;
                }
            }
        }
        cur_elem = cur_elem->next;
    }

    return FALSE;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_activate       |
+--------------------------------------------------------------------+

  PURPOSE : Start SIM card activation

*/

void sim_activate (void)
{
    TRACE_FUNCTION("sim_activate()");

    /* 
     * Full functionality is used donīt reset the ME 
     */
    if (sAT_PlusCFUN(CMD_SRC_LCL,CFUN_FUN_Full,CFUN_RST_NotPresent)
        NEQ AT_EXCT)
    {
        TRACE_ERROR("sAT_PlusCFUN error");
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_spn_req        |
+--------------------------------------------------------------------+

  PURPOSE : Request service provider name

*/

void sim_spn_req (void)
{
    T_EF_SPN spn;

    TRACE_FUNCTION("sim_spn_req()");

    memset(&spn,0,sizeof(T_EF_SPN));

    if (sim_check_service(17,sim_service_table)
        EQ ALLOCATED_AND_ACTIVATED)
        sim_read_sim(SIM_SPN,17,17);
    else
        nm_spn_cnf(&spn);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_ok_cfun        |
+--------------------------------------------------------------------+

  PURPOSE : Notify successful end of SIM card activation

*/

void sim_ok_cfun (void)
{
    T_ACI_CFUN_FUN fun;

    TRACE_FUNCTION ("sim_ok_cfun()");

    qAT_PlusCFUN( CMD_SRC_LCL, &fun );

    if( fun EQ CFUN_FUN_Full )
    {
      sim_stat = SIM_ACTIVE;
      sim_status.sim_status = MFW_SIM_NO_PIN;
      sim_status.sim_operation_mode = sim_config.oper_mode;
      sim_status.sim_pin_retries = 0;
      sim_status.sim_procedure = MFW_SIM_ACTIVATION;
      sim_status.sim_status_type = pin_ident;

      pin_ident = MFW_SIM_UNKNOWN;
      sim_signal(E_SIM_STATUS,&sim_status);
      nm_activate(MFW_SIM_NO_PIN);

      pin1_set = MFW_SIM_DISABLE;
    }
    else if( fun EQ CFUN_FUN_Minimum )
    {
	    nm_ok_deregistration();
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_error_cfun     |
+--------------------------------------------------------------------+

  PURPOSE : Notify error status of SIM card

*/

void sim_error_cfun (U8 result)
{
    TRACE_FUNCTION("sim_error_cfun()");

    sim_status.sim_procedure = MFW_SIM_ACTIVATION;
    sim_status.sim_operation_mode = sim_config.oper_mode;

    switch (result)
    {
        case CME_ERR_SimPinReq:         /* PIN 1 must be entered    */
            sim_status.sim_status = MFW_SIM_PIN_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN1);
            sim_status.sim_status_type = MFW_SIM_PIN1;
            sim_stat = SIM_ACTIVE;
            break;
        case CME_ERR_SimPin2Req:        /* PIN 2 must be entered    */
            sim_status.sim_status = MFW_SIM_PIN2_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN2);
            sim_status.sim_status_type = MFW_SIM_PIN2;
            sim_stat = SIM_ACTIVE;
            break;
        case CME_ERR_SimPukReq:         /* PUK 1 must be entered    */
            sim_status.sim_status = MFW_SIM_PUK_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PUK1);
            sim_status.sim_status_type = MFW_SIM_PUK1;
            sim_stat = SIM_ACTIVE;
            break;
        case CME_ERR_SimPuk2Req:        /* PUK 2 must be entered    */
            sim_status.sim_status = MFW_SIM_PUK2_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PUK2);
            sim_status.sim_status_type = MFW_SIM_PUK2;
            sim_stat = SIM_ACTIVE;
            break;
        case CME_ERR_SimFail:           /* SIM card is invalid      */
        case CME_ERR_SimWrong:
            sim_status.sim_status = MFW_SIM_INVALID_CARD;
            sim_status.sim_pin_retries = 0;
            sim_status.sim_status_type = MFW_SIM_UNKNOWN;
            sim_stat = SIM_NOT_ACTIVE;
            break;
        case CME_ERR_SimNotIns:         /* no SIM card inserted     */
            sim_status.sim_status = MFW_SIM_NO_SIM_CARD;
            sim_status.sim_pin_retries = 0;
            sim_status.sim_status_type = MFW_SIM_UNKNOWN;
            sim_stat = SIM_NOT_ACTIVE;
            break;
        default:
            TRACE_ERROR("sim_error_cfun(): result");
            return;
    }

    sim_signal(E_SIM_STATUS,&sim_status);

    if ((result == CME_ERR_SimPinReq)
        OR (result == CME_ERR_SimPukReq))
        pin1_set = MFW_SIM_ENABLE;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_error_cpin     |
+--------------------------------------------------------------------+

  PURPOSE : Inform about error of PIN entering or PUK entering

*/

void sim_error_cpin (T_ACI_CME_ERR reason)
{
    T_ACI_CPIN_RSLT code;

    TRACE_FUNCTION("sim_error_cpin()");

    sim_status.sim_procedure = pin_flag;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    sim_status.sim_status = MFW_SIM_FAILURE;
    sim_status.sim_status_type = pin_ident;

	  pin_flag = -1;
	  pin_ident = MFW_SIM_UNKNOWN;

    switch (reason)
    {
        case CME_ERR_WrongPasswd:
            if (qAT_PlusCPIN(CMD_SRC_LCL,&code) != AT_CMPL)
            {
                TRACE_ERROR("sim_error_cpin():CPIN? failed");
                sim_signal(E_SIM_STATUS,&sim_status);
                return;
            }
            break;
        case CME_ERR_SimWrong:
			sim_status.sim_status = MFW_SIM_INVALID_CARD;
            sim_signal(E_SIM_STATUS,&sim_status);
            return;
        default:
            TRACE_ERROR("sim_error_cpin():Ill reason");
            sim_signal(E_SIM_STATUS,&sim_status);
            return;
    }

    switch (code)
    {
        case CPIN_RSLT_SimPinReq:
            sim_status.sim_status = MFW_SIM_PIN_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN1);
            break;
        case CPIN_RSLT_SimPukReq:
            sim_status.sim_status = MFW_SIM_PUK_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PUK1);
            break;
        case CPIN_RSLT_SimPin2Req:
            sim_status.sim_status = MFW_SIM_PIN2_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN2);
            break;
        case CPIN_RSLT_SimPuk2Req:
            sim_status.sim_status = MFW_SIM_PUK2_REQ;
            sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PUK2);
            break;
        case CPIN_RSLT_NotPresent:
        case CPIN_RSLT_SimReady:
        default:
            TRACE_ERROR("sim_error_cpin():Ill code");
            break;
    }

    sim_signal(E_SIM_STATUS,&sim_status);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_ok_cpin        |
+--------------------------------------------------------------------+

  PURPOSE : Successful end of PIN entering or PUK entering

*/

void sim_ok_cpin (void)
{
    TRACE_FUNCTION("sim_ok_cpin()");

    switch (pin_flag)
    {
        case MFW_SIM_VERIFY:
            sim_status.sim_procedure = MFW_SIM_VERIFY;
            sim_status.sim_status = MFW_SIM_NO_PIN;
            sim_status.sim_status_type = pin_ident;
            break;
        case MFW_SIM_UNBLOCK:
            sim_status.sim_procedure = MFW_SIM_UNBLOCK;
            sim_status.sim_status = MFW_SIM_SUCCESS;
            sim_status.sim_status_type = pin_ident;
            break;
        default:
            break;
    }

    pin_flag = -1;
	  pin_ident = MFW_SIM_UNKNOWN;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    sim_status.sim_pin_retries = 0;

    sim_signal (E_SIM_STATUS, &sim_status);
    if (nm_reg_flag_req())
      nm_activate(MFW_SIM_NO_PIN);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_ss_unblock     |
+--------------------------------------------------------------------+

  PURPOSE : SIM unblock via SS string

*/

void sim_ss_unblock(UBYTE result, T_ACI_CME_ERR reason)
{
    TRACE_FUNCTION("sim_ss_unblock()");
        
    pin_flag = MFW_SIM_UNBLOCK;

    if (result == SIM_UBLK_ERROR)
        sim_error_cpin (reason);
    if (result == SIM_UBLK_OK)
        sim_ok_cpin ();
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_verify_pin     |
+--------------------------------------------------------------------+

  PURPOSE : Verify PIN

*/

void sim_verify_pin (U8 pin_id, char *pin)
{
	TRACE_FUNCTION("sim_verify_pin()");

    pin_flag = MFW_SIM_VERIFY;
	  pin_ident = pin_id;
    switch (pin_id)
    {
        case MFW_SIM_PIN1:
            sAT_PercentPVRF(CMD_SRC_LCL, PVRF_TYPE_Pin1, pin, 0);
            break;
        case MFW_SIM_PIN2:
            sAT_PercentPVRF(CMD_SRC_LCL, PVRF_TYPE_Pin2, pin, 0);
            break;
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_unblock_pin    |
+--------------------------------------------------------------------+

  PURPOSE : unblock SIM

*/

void sim_unblock_pin (U8 pin_id, char *puk, char *newpin)
{
    TRACE_FUNCTION("sim_unblock_pin()");

    pin_flag = MFW_SIM_UNBLOCK;
	  pin_ident = pin_id;
    switch (pin_id)
    {
        case MFW_SIM_PUK1:
            sAT_PercentPVRF(CMD_SRC_LCL, PVRF_TYPE_Puk1, puk, newpin);
            break;
        case MFW_SIM_PUK2:
            sAT_PercentPVRF(CMD_SRC_LCL, PVRF_TYPE_Puk2, puk, newpin);
            break;
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_change_pin     |
+--------------------------------------------------------------------+

  PURPOSE : Request of PIN change

*/

void sim_change_pin (U8 pin_id, U8 *old_pin, U8 *new_pin)
{
    TRACE_FUNCTION("sim_change_pin()");

    pin_ident = pin_id;
    switch (pin_id)
    {
        case MFW_SIM_PIN1:
            sAT_PlusCPWD(CMD_SRC_LCL, CPWD_FAC_Sc,
                         (char *)old_pin, (char *)new_pin);
            break;
        case MFW_SIM_PIN2:
            sAT_PlusCPWD(CMD_SRC_LCL, CPWD_FAC_P2,
                         (char *)old_pin, (char *)new_pin);
            break;
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_ok_cpinc       |
+--------------------------------------------------------------------+

  PURPOSE : Notify successful end of PIN change

*/

void sim_ok_cpinc (void)
{
    TRACE_FUNCTION("sim_ok_cpinc()");

    sim_status.sim_procedure = MFW_SIM_CHANGE;
    sim_status.sim_status = MFW_SIM_SUCCESS;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    sim_status.sim_pin_retries = 0;
    sim_status.sim_status_type = pin_ident;

    pin_ident = MFW_SIM_UNKNOWN;
    sim_signal(E_SIM_STATUS,&sim_status);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_error_cpinc    |
+--------------------------------------------------------------------+

  PURPOSE : Notify failed PIN change

*/

void sim_error_cpinc (void)
{
    TRACE_FUNCTION("sim_error_cpinc()");

    sim_status.sim_procedure = MFW_SIM_CHANGE;
    sim_status.sim_status = MFW_SIM_FAILURE;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    if (pin_ident EQ MFW_SIM_PIN1)
      sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN1);
    else if (pin_ident EQ MFW_SIM_PIN2)
      sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN2);
    else
      sim_status.sim_pin_retries = 0;
    sim_status.sim_status_type = pin_ident;

    pin_ident = MFW_SIM_UNKNOWN;
    sim_signal(E_SIM_STATUS,&sim_status);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_disable_pin    |
+--------------------------------------------------------------------+

  PURPOSE : Request PIN disability

*/

void sim_disable_pin (U8 *pin)
{
    TRACE_FUNCTION("sim_disable_pin()");

    ss_set_clck(CLCK_FAC_Sc, CLCK_MOD_Unlock,
               (char *)pin, -1, MFW_SIM_CPIND);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_ok_cpind       |
+--------------------------------------------------------------------+

  PURPOSE : Successful end of PIN disability

*/

void sim_ok_cpind (void)
{
    TRACE_FUNCTION("sim_ok_cpind()");

    sim_status.sim_procedure = MFW_SIM_DISABLE;
    sim_status.sim_status = MFW_SIM_SUCCESS;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    sim_status.sim_pin_retries = 0;
    sim_status.sim_status_type = MFW_SIM_UNKNOWN; // no indication

    pin1_set = MFW_SIM_DISABLE;
    sim_signal(E_SIM_STATUS,&sim_status);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_error_cpind    |
+--------------------------------------------------------------------+

  PURPOSE : Failed PIN disability

*/

void sim_error_cpind (void)
{
    TRACE_FUNCTION("sim_error_cpind()");

    sim_status.sim_procedure = MFW_SIM_DISABLE;
    sim_status.sim_status = MFW_SIM_FAILURE;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN1);
    sim_status.sim_status_type = MFW_SIM_UNKNOWN; // no indication

    sim_signal(E_SIM_STATUS,&sim_status);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_enable_pin     |
+--------------------------------------------------------------------+

  PURPOSE : Request PIN enability

*/

void sim_enable_pin (U8 *pin)
{
    TRACE_FUNCTION("sim_enable_pin()");

    ss_set_clck(CLCK_FAC_Sc, CLCK_MOD_Lock,
               (char *)pin, -1, MFW_SIM_CPINE);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_ok_cpine       |
+--------------------------------------------------------------------+

  PURPOSE : Successful end of PIN enability

*/

void sim_ok_cpine()
{
    TRACE_FUNCTION("sim_ok_cpine()");

    sim_status.sim_procedure = MFW_SIM_ENABLE;
    sim_status.sim_status = MFW_SIM_SUCCESS;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    sim_status.sim_pin_retries = 0;
    sim_status.sim_status_type = MFW_SIM_UNKNOWN; // no indication

    pin1_set = MFW_SIM_ENABLE;
    sim_signal(E_SIM_STATUS,&sim_status);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_error_cpine    |
+--------------------------------------------------------------------+

  PURPOSE : Failed PIN enability

*/

void sim_error_cpine (void)
{
    TRACE_FUNCTION("sim_error_cpine()");

    sim_status.sim_procedure = MFW_SIM_ENABLE;
    sim_status.sim_status = MFW_SIM_FAILURE;
    sim_status.sim_operation_mode = sim_config.oper_mode;
    sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN1);
    sim_status.sim_status_type = MFW_SIM_UNKNOWN; // no indication

    sim_signal(E_SIM_STATUS,&sim_status);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)         MODULE  : MFW_SIM           |
| STATE   : code                         ROUTINE : sim_check_service |
+--------------------------------------------------------------------+

  PURPOSE : Checks a service status

*/

U8 sim_check_service (U8 nr, U8 *serv_table)
{
    U8 value;

    TRACE_FUNCTION("sim_check_service()");

    value = *(serv_table + (nr - 1) / 4);
    value >>=  ((nr - 1) & 3) * 2;

    return (value & 3);
}


/*
+-----------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)         MODULE  : MFW_SIM              |
| STATE   : code                         ROUTINE : sim_serv_table_check |
+-----------------------------------------------------------------------+

  PURPOSE : Checks a service status in SIM service table

*/

T_MFW sim_serv_table_check(UBYTE serv_num)
{
  TRACE_FUNCTION("sim_serv_table_check()");
  return sim_check_service(serv_num, sim_service_table);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)         MODULE  : MFW_SIM           |
| STATE   : code                         ROUTINE : rAT_PlusCFUNP     |
+--------------------------------------------------------------------+

  PURPOSE : MMI relevant parameters from the SIM card

*/

void rAT_PlusCFUNP (T_SIM_MMI_INSERT_IND *mmi_insert_ind)
{
    TRACE_FUNCTION("rAT_PlusCFUNP()");

    sim_stat = SIM_ACTIVE;

    sim_config.oper_mode = mmi_insert_ind->func;
    //  sms_mmi_parameter(mmi_insert_ind->cbmid);
    nm_mmi_parameters(&mmi_insert_ind->imsi_field,
                        &mmi_insert_ind->pref_plmn);
    memcpy(sim_service_table,mmi_insert_ind->sim_serv,
                                sizeof(sim_service_table));
    //memcpy(sim_config.deper_key,mmi_insert_ind->deper_key,
    //                            sizeof(sim_config.deper_key));
    sim_config.phase = mmi_insert_ind->phase;
    sim_config.access_acm = mmi_insert_ind->access_acm;
    sim_config.access_acmmax = mmi_insert_ind->access_acmmax;
    sim_config.access_puct = mmi_insert_ind->access_puct;

//    sim_init_sim_insert();

    if (sim_check_service(15,sim_service_table)
        == ALLOCATED_AND_ACTIVATED)
        sim_read_sim(SIM_GID1, NOT_PRESENT_8BIT, 5);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)         MODULE  : MFW_SIM           |
| STATE   : code                         ROUTINE : sim_mmi_parameter |
+--------------------------------------------------------------------+

  PURPOSE : MMI relevant parameters from the SIM card

*/

void sim_mmi_parameter(T_SIM_ACTIVATE_CNF *sim_act_cnf)
{
  TRACE_FUNCTION("sim_mmi_parameter()");

  memcpy( sim_config.pref_lang, sim_act_cnf->pref_lang, 5);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)         MODULE  : MFW_SIM           |
| STATE   : code                         ROUTINE : sim_gid1_cnf      |
+--------------------------------------------------------------------+

  PURPOSE : read SIM group identifier 1 from SIM card

*/

void sim_gid1_cnf(SHORT error, UBYTE *data)
{
  TRACE_FUNCTION("sim_gid1_cnf()");

  if (error EQ SIM_NO_ERROR)
    memcpy(sim_config.sim_gidl1, data, 5);

  if (!sat_update)
  {
    if (sim_check_service(16,sim_service_table)
        == ALLOCATED_AND_ACTIVATED)
        sim_read_sim(SIM_GID2, NOT_PRESENT_8BIT, 5);
  }
#ifdef SIM_TOOLKIT
  else
  {
    sat_update = FALSE;
    satUpdateFiles ( TRUE, SIM_GID1 );
  }
#endif
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)         MODULE  : MFW_SIM           |
| STATE   : code                         ROUTINE : sim_gid2_cnf      |
+--------------------------------------------------------------------+

  PURPOSE : read SIM group identifier 2 from SIM card

*/

void sim_gid2_cnf(SHORT error, UBYTE *data)
{
  TRACE_FUNCTION("sim_gid2_cnf()");
  if (error EQ SIM_NO_ERROR)
    memcpy(sim_config.sim_gidl2, data, 5);

#ifdef SIM_TOOLKIT
  if ( sat_update )
  {
    sat_update = FALSE;
    satUpdateFiles ( TRUE, SIM_GID2 );
  }
#endif
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_save_pref_lang |
+--------------------------------------------------------------------+

  PURPOSE : save preferred language

*/

void sim_save_pref_lang (UBYTE *lang, UBYTE len)
{
  UBYTE sim_data[7];
  UBYTE i;

  TRACE_FUNCTION("sim_save_pref_lang()");

  //
  // copy a maximum of 5 bytes for storing on the SIM card
  //
  for (i=0;i<len AND i<5;i++)
    sim_data[i] = lang[i];

  //
  // if less than 5 bytes fill with dummy values
  //
  for (i=len; i<5;i++)
    sim_data[i] = 0xFF;

  //
  // write to the SIM card
  //
  sim_write_sim(SIM_LP, sim_data, 5);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : rAT_PercentSIMREM  |
+--------------------------------------------------------------------+

  PURPOSE : call back for SIM removed

*/

void rAT_PercentSIMREM( T_ACI_SIMREM_TYPE srType )
{
    TRACE_FUNCTION("rAT_PercentSIMREM()");

    if ( srType EQ SIMREM_FAILURE )
    {
      sim_status.sim_procedure = MFW_SIM_REMOVED;
      sim_status.sim_status = MFW_SIM_NO_SIM_CARD;
      sim_status.sim_operation_mode = sim_config.oper_mode;
      sim_status.sim_pin_retries = 0;
      sim_status.sim_status_type = MFW_SIM_UNKNOWN;
      sim_stat = SIM_NOT_ACTIVE;
      sim_signal(E_SIM_STATUS,&sim_status);
    }
    else if ( srType EQ SIMREM_RESET )
    {
#ifdef SIM_TOOLKIT
      sim_signal(E_SIM_RESET, 0); 
#endif
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : rAT_percentSIMINS  |
+--------------------------------------------------------------------+

  PURPOSE : call back for SIM inserted

*/

void rAT_PercentSIMINS( T_ACI_CME_ERR err )
{
    TRACE_FUNCTION("rAT_percentSIMINS()");

    sim_signal(E_SIM_INSERTED, 0);

    switch ( err )
    {
      case CME_ERR_SimPinReq:
        sim_status.sim_status = MFW_SIM_PIN_REQ;
        sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PIN1);
        sim_status.sim_status_type = MFW_SIM_PIN1;
        sim_stat = SIM_ACTIVE;
        sim_signal(E_SIM_STATUS, &sim_status);
        break;

      case CME_ERR_SimPukReq:
        sim_status.sim_status = MFW_SIM_PUK_REQ;
        sim_status.sim_pin_retries = sim_pin_count(MFW_SIM_PUK1);
        sim_status.sim_status_type = MFW_SIM_PUK1;
        sim_stat = SIM_ACTIVE;
        sim_signal(E_SIM_STATUS, &sim_status);
        break;

      default:
        break;
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_configuration  |
+--------------------------------------------------------------------+

  PURPOSE : Request the configuration of SIM card

*/

UBYTE sim_cvt_access_status(UBYTE acs)
{
    TRACE_FUNCTION("sim_cvt_access_status()");
    
    switch(acs)
    {
        case ACCESS_ALWAYS: return MFW_SIM_NO_PIN;
        case ACCESS_PIN_1:  return MFW_SIM_PIN1;
        case ACCESS_PIN_2:  return MFW_SIM_PIN2;
        default:            return MFW_SIM_UNKNOWN;
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_configuration  |
+--------------------------------------------------------------------+

  PURPOSE : Request the configuration of SIM card

*/

MfwRes sim_configuration (U8 *phase, U8 *serv, U8 *slen,
                          U8 *lang, U8 *llen,
                          T_MFW_AOC_ACCESS *access)
{
    U8 l;
    TRACE_FUNCTION("sim_configuration()");

		//PATCH2 TB 1310: Add test of NULL parameter to avoid to declare parameter of unwanted data
    if (sim_stat != SIM_ACTIVE)
        return MFW_SIM_FAILURE;

		if (phase != NULL)
			*phase = sim_config.phase;

		if ((serv != NULL) && (slen != NULL))
		{			
			l = sizeof(sim_service_table);
			if (l < *slen)
					*slen = l;
			memcpy(serv,sim_service_table,*slen);
		}

    //PATCH1 TB 1310: replace slen by llen
		if ((lang != NULL) && (llen != NULL))
		{
			l = sizeof(sim_config.pref_lang);
			if (l < *llen)
					*llen = l;
			memcpy(lang, sim_config.pref_lang, *llen);
		}
		//END PATCH1 TB

		if (access != NULL)
		{
			access->access_acm    = sim_cvt_access_status(sim_config.access_acm);
			access->access_acmmax = sim_cvt_access_status(sim_config.access_acmmax);
			access->access_puct   = sim_cvt_access_status(sim_config.access_puct);
		}
		//END PATCH2 TB

    return MFW_SIM_SUCCESS;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_status_check   |
+--------------------------------------------------------------------+

  PURPOSE : check activation of SIM card

*/

int sim_status_check (void)
{
    TRACE_FUNCTION("sim_status_check()");

    return sim_stat;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_pin_count      |
+--------------------------------------------------------------------+

  PURPOSE : Request PIN/PUK count

*/

int sim_pin_count(U8 pin_id)
{
    SHORT        pn1Cnt;
    SHORT        pn2Cnt;
    SHORT        pk1Cnt;
    SHORT        pk2Cnt;
    T_ACI_PVRF_STAT ps1;
    T_ACI_PVRF_STAT ps2;
        
    TRACE_FUNCTION("sim_pin_count()");


    if (qAT_PercentPVRF(CMD_SRC_LCL, &pn1Cnt,
                        &pn2Cnt, &pk1Cnt, &pk2Cnt, &ps1, &ps2) != AT_CMPL)
        return -1;

    switch (pin_id)
    {
        case MFW_SIM_PIN1:  return pn1Cnt;
        case MFW_SIM_PIN2:  return pn2Cnt;
        case MFW_SIM_PUK1:  return pk1Cnt;
        case MFW_SIM_PUK2:  return pk2Cnt;
        default:            return -1;
    }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : simDecodeB2A       |
+--------------------------------------------------------------------+

  PURPOSE : convert bcd to ASCII

*/

void simDecodeB2A (U8 *ci, U8 li, U8 *di)
{
    int i;
    
    TRACE_FUNCTION("simDecodeB2A()");

    for (i = 0; i < li * 2; i++)
    {
        di[i] = (i & 1) ? (ci[i/2] >> 4) + '0'
                        : (ci[i/2] & 0x0f) + '0';
        if (di[i] > '9')
        {
            di[i] = 0;
            break;
        }
    }
    di[i] = 0;
}


/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM             |
| STATE   : code                        ROUTINE : sim_unlock_sim_lock |
+---------------------------------------------------------------------+

  PURPOSE : de-personalisation for SIM lock.

*/

T_MFW sim_unlock_sim_lock(UBYTE type, UBYTE *passwd)
{
  UBYTE        eep_ckey [LONG_NAME];  // extracted version of PCM content          
  EF_SIMLCKEXT simlck;

  TRACE_FUNCTION("sim_unlock_sim_lock()");

  /*
   * Read SIM LOCK Record from PCM
   */
  if (sim_get_sim_lock (&simlck) NEQ PCM_OK)
  {
    TRACE_ERROR("No SIMLCK");
    return MFW_SIM_UNLOCK_ERR;
  }

  /*
   * check whether card is already blocked
   */
	if (simlck.cnt >= simlck.maxcnt)
		return MFW_SIM_BLOCKED;

  switch (type)
  {
    /*
     * N-Lock
     */
    case MFW_SIM_NLOCK:
      /*
       * Extract Key from PCM record
       */
      simDecodeB2A (simlck.NKey, 8, eep_ckey);
      if (!strcmp((char *)eep_ckey, (char *)passwd))
			{
        /*
         * unblock password is okay
         */
				sim_nlock     = SIMLOCK_ENABLED;
				simlck.locks1 = (UBYTE) FldSet(simlck.locks1,nlock,sim_nlock);
				simlck.cnt    = 0;
				sim_set_sim_lock (&simlck);

				return MFW_SIM_NLOCK;
			}
			break;

    /*
     * SP-Lock
     */
    case MFW_SIM_SPLOCK:
      /*
       * Extract Key from PCM record
       */
      simDecodeB2A (simlck.SPKey, 8, eep_ckey);
      if (!strcmp((char *)eep_ckey, (char *)passwd))
      {
        /*
         * unblock password is okay
         */
				sim_splock    = SIMLOCK_ENABLED;
				simlck.locks1 = (UBYTE) FldSet(simlck.locks1,splock,sim_splock);
				simlck.cnt    = 0;
				sim_set_sim_lock (&simlck);

        return MFW_SIM_SPLOCK;
			}
			break;
    
    /*
     * NS-Lock
     */
    case MFW_SIM_NSLOCK:
      /*
       * Extract Key from PCM record
       */
      simDecodeB2A (simlck.NSKey, 8, eep_ckey);
      if (!strcmp((char *)eep_ckey, (char *)passwd))
      {
        /*
         * unblock password is okay
         */
   			sim_nslock    = SIMLOCK_ENABLED;
				simlck.locks1 = (UBYTE) FldSet(simlck.locks1,nslock,sim_nslock);
				simlck.cnt    = 0;
				sim_set_sim_lock (&simlck);

				return MFW_SIM_NSLOCK;
			}
			break;

    /*
     * C-Lock
     */
    case MFW_SIM_CLOCK:
      /*
       * Extract Key from PCM record
       */
      simDecodeB2A (simlck.CKey, 8, eep_ckey);
      if (!strcmp((char *)eep_ckey, (char *)passwd))
      {
        /*
         * unblock password is okay
         */
				sim_clock     = SIMLOCK_ENABLED;
				simlck.locks2 = (UBYTE) FldSet(simlck.locks2,clock,sim_clock);
				simlck.cnt    = 0;
				sim_set_sim_lock (&simlck);

				return MFW_SIM_CLOCK;
			}
			break;

    /*
     * P-Lock
     */
    case MFW_SIM_PLOCK:
      /*
       * Extract Key from PCM record
       */
      simDecodeB2A (simlck.PKey, 8, eep_ckey);
      if (!strcmp((char *)eep_ckey, (char *)passwd))
      {
        /*
         * unblock password is correct
         */
				sim_plock     = SIMLOCK_ENABLED;
				simlck.locks1 = (UBYTE) FldSet(simlck.locks1,plock,sim_plock);
				simlck.cnt    = 0;
				sim_set_sim_lock (&simlck);

				return MFW_SIM_PLOCK;
			}
			break;

    default:
      return MFW_SIM_UNLOCK_ERR;
  }

  /*
   * another failed attempt
   * increment counter, store in PCM and may change the status
   */
	simlck.cnt++;
	sim_set_sim_lock (&simlck);

	if (simlck.cnt >= simlck.maxcnt)
	{
		sim_blocked = TRUE;    
		return MFW_SIM_BLOCKED;
	}
	else
		return MFW_SIM_UNLOCK_ERR;
}

/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM             |
| STATE   : code                        ROUTINE : sim_check_sim_Plock |
+---------------------------------------------------------------------+

  PURPOSE : check SIM lock

*/

int sim_check_sim_Plock (void)
{
  EF_SIMLCKEXT simlck;
  UBYTE        i;

  TRACE_FUNCTION ("sim_check_sim_Plock()");


	if (sim_blocked EQ TRUE OR 
      sim_plock   EQ SIMLOCK_BLOCKED)
  {
    /*
     * Try to reset unlock attempt counter
     */
    sim_check_unblock_sim (&simlck);
		return MFW_SIM_BLOCKED;
  }

  /* 
   * lock check disabled      
   */
  if (sim_plock EQ SIMLOCK_DISABLED) 
    return MFW_SIM_DISABLE;

  /* 
   * lock check blocked      
   */
  if (sim_plock EQ SIMLOCK_LOCKED)              
    return MFW_SIM_LOCKED;

  /*
   * lock check enabled       
   */
  if (sim_plock EQ SIMLOCK_ENABLED)              
  {
    if (sim_get_sim_lock (&simlck) NEQ PCM_OK)
    {
      TRACE_ERROR("No SIMLCK");
      return MFW_SIM_FAILURE;     
    }

    /*
     * Check all digits
     */
		for (i=0; i<simlck.len_p_imsi; i++)
		{
			if (sim_check_imsi_digit(simlck.p_imsi[i], mfw_IMSI[i]) EQ FALSE)
				break;
		}
    
    /*
     * all digits okay
     */
		if (i EQ simlck.len_p_imsi)
			return MFW_SIM_ENABLE;

    /*
     * P-LOCK check failed
     */

    sim_plock     = SIMLOCK_LOCKED;
		simlck.locks1 = (UBYTE) FldSet(simlck.locks1,plock,sim_plock);
		sim_set_sim_lock (&simlck);
    return MFW_SIM_LOCKED;
  }

  /*
   * shall not happen
   */
  return MFW_SIM_FAILURE;
}


/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM             |
| STATE   : code                        ROUTINE : sim_check_sim_Nlock |
+---------------------------------------------------------------------+

  PURPOSE : Check network lock

*/

int sim_check_sim_Nlock (void)
{
  EF_SIMLCKEXT simlck;
	UBYTE        i;

  TRACE_FUNCTION ("sim_check_sim_Nlock()");

	if (sim_blocked EQ TRUE OR 
      sim_nlock   EQ SIMLOCK_BLOCKED)
  {
    /*
     * Try to reset unlock attempt counter
     */
    sim_check_unblock_sim (&simlck);
		return MFW_SIM_BLOCKED;
  }

  /*
   * lock check disabled
   */
  if (sim_nlock EQ SIMLOCK_DISABLED)             
    return MFW_SIM_DISABLE;

  /*
   * lock check blocked
   */
  if (sim_nlock EQ SIMLOCK_LOCKED)            
        return MFW_SIM_LOCKED;

  /*
   * lock check enabled
   */
  if (sim_nlock EQ SIMLOCK_ENABLED)
  {
    if (sim_get_sim_lock (&simlck) NEQ PCM_OK)
    {
      TRACE_ERROR("No SIMLCK");
      return MFW_SIM_FAILURE;     
    }

    /*
     * check all digits
     */
		for (i=0; i<simlck.len_n_imsi; i++)	
    {
      if (sim_check_imsi_digit(simlck.n_imsi[i], mfw_IMSI[i]) EQ FALSE)
				break;
		}

    /*
     * all digits okay
     */
		if (i EQ simlck.len_n_imsi)
			return MFW_SIM_ENABLE;

    /*
     * N-LOCK check failed
     */
    sim_nlock     = SIMLOCK_LOCKED;
		simlck.locks1 = (U8) FldSet(simlck.locks1,nlock,sim_nlock);
		sim_set_sim_lock (&simlck);
    return MFW_SIM_LOCKED;
  }
  /*
   * shall not happen
   */
  return MFW_SIM_FAILURE;
}


/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM             |
| STATE   : code                        ROUTINE : sim_check_sim_SPlock|
+---------------------------------------------------------------------+

  PURPOSE : Check SIM service provider lock. It only works with SIMs
            which support GID1 file.

*/

int sim_check_sim_SPlock (void)
{
  EF_SIMLCKEXT simlck;
	UBYTE        i;

  TRACE_FUNCTION ("sim_check_sim_SPlock()");

  /*
   * Only if Service 15 is activated and allocated
   */
  if (sim_check_service(15,sim_service_table) NEQ ALLOCATED_AND_ACTIVATED)
    return MFW_SIM_FAILURE;

	if (sim_blocked EQ TRUE OR 
      sim_splock  EQ SIMLOCK_BLOCKED)
  {
    /*
     * Try to reset unlock attempt counter
     */
    sim_check_unblock_sim (&simlck);
		return MFW_SIM_BLOCKED;
  }

  /*
   * lock check disabled
   */
  if (sim_splock EQ SIMLOCK_DISABLED)
    return MFW_SIM_DISABLE;

  /*
   * lock check blocked
   */
  if (sim_splock EQ SIMLOCK_LOCKED)
    return MFW_SIM_LOCKED;

  /*
   * lock check enabled
   */
  if (sim_splock EQ SIMLOCK_ENABLED)             
  {
    if (sim_get_sim_lock (&simlck) NEQ PCM_OK)
    {
      TRACE_ERROR("No SIMLCK");
      return MFW_SIM_FAILURE;     
    }

    /* 
     * check SP group identifier 
     */
    if (memcmp(&simlck.gidl1, sim_config.sim_gidl1, 1))
    {
      sim_splock    = SIMLOCK_LOCKED;
			simlck.locks1 = (UBYTE) FldSet(simlck.locks1,splock,sim_splock);
			sim_set_sim_lock (&simlck);
      
      return MFW_SIM_LOCKED;
    }

    /* 
     * check all digits
     */
		for (i=0; i<simlck.len_sp_imsi; i++)
		{
			if (sim_check_imsi_digit(simlck.sp_imsi[i], mfw_IMSI[i]) EQ FALSE)
				break;
		}

    /*
     * all digits okay
     */
		if (i EQ simlck.len_sp_imsi)
			return MFW_SIM_ENABLE;

    /*
     * failed SP-Lock
     */
    sim_splock    = SIMLOCK_LOCKED;
		simlck.locks1 = (UBYTE) FldSet(simlck.locks1,splock,sim_splock);
		sim_set_sim_lock (&simlck);

    return MFW_SIM_LOCKED;
  }
  /*
   * shall not happen
   */
  return MFW_SIM_FAILURE;
}


/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM             |
| STATE   : code                        ROUTINE : sim_check_sim_NSlock|
+---------------------------------------------------------------------+

  PURPOSE : Check network subset lock

*/

int sim_check_sim_NSlock (void)
{
  EF_SIMLCKEXT simlck;
	UBYTE        i;

  TRACE_FUNCTION ("sim_check_sim_NSlock()");

	if (sim_blocked EQ TRUE OR 
      sim_nslock  EQ SIMLOCK_BLOCKED)
  {
    /*
     * Try to reset unlock attempt counter
     */
    sim_check_unblock_sim (&simlck);
		return MFW_SIM_BLOCKED;
  }

  /* 
   * lock check disabled
   */
  if (sim_nslock EQ SIMLOCK_DISABLED)
    return MFW_SIM_DISABLE;

  /*
   * lock check blocked
   */
  if (sim_nslock EQ SIMLOCK_LOCKED)
    return MFW_SIM_LOCKED;

  /*
   * lock check enabled
   */
  if (sim_nslock EQ SIMLOCK_ENABLED)
  {
    if (sim_get_sim_lock (&simlck) NEQ PCM_OK)
    {
      TRACE_ERROR("No SIMLCK");
      return MFW_SIM_FAILURE;     
    }

    /*
     * check all digits
     */
    for (i=0; i<simlck.len_ns_imsi; i++)
		{
			if (sim_check_imsi_digit(simlck.ns_imsi[i], mfw_IMSI[i]) EQ FALSE)
				break;
		}

    /*
     * all digits okay
     */
		if (i EQ simlck.len_ns_imsi)
			return MFW_SIM_ENABLE;

    /*
     * Lock has failed
     */
    sim_nslock    = SIMLOCK_LOCKED;
		simlck.locks1 = (UBYTE) FldSet(simlck.locks1,nslock,sim_nslock);
		sim_set_sim_lock (&simlck);

    return MFW_SIM_LOCKED;
  }

  /*
   * shall not happen
   */
  return MFW_SIM_FAILURE;
}

/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM             |
| STATE   : code                        ROUTINE : sim_check_sim_Clock |
+---------------------------------------------------------------------+

  PURPOSE : Check corporate lock. It only works with SIMs
            which support GID1 and GID2 files.

*/

int sim_check_sim_Clock (void)
{
  EF_SIMLCKEXT simlck;
  UBYTE        i;

  TRACE_FUNCTION ("sim_check_sim_Clock()");

  /* 
   * check the SIM supports GID1 and GID2 
   */
  if (sim_check_service(15,sim_service_table) NEQ ALLOCATED_AND_ACTIVATED)
    return MFW_SIM_FAILURE;

  if (sim_check_service(16,sim_service_table) NEQ ALLOCATED_AND_ACTIVATED)
    return MFW_SIM_FAILURE;

	if (sim_blocked EQ TRUE OR
      sim_clock   EQ SIMLOCK_BLOCKED)
  {
    /*
     * Try to reset unlock attempt counter
     */
    sim_check_unblock_sim (&simlck);
		return MFW_SIM_BLOCKED;
  }

  /*
   * lock check disabled
   */
  if (sim_clock EQ SIMLOCK_DISABLED)
    return MFW_SIM_DISABLE;

  /*
   * lock check blocked
   */
  if (sim_clock EQ SIMLOCK_LOCKED)
    return MFW_SIM_LOCKED;

  /*
   * lock check enabled
   */
  if (sim_clock EQ SIMLOCK_ENABLED)            
  {
    if (sim_get_sim_lock (&simlck) NEQ PCM_OK)
    {
      TRACE_ERROR("No SIMLCK");
      return MFW_SIM_FAILURE;     
    }

    /* 
     * check SP group identifier 1 and 2 
     */
    if (simlck.gidl1 NEQ sim_config.sim_gidl1[0] OR 
        simlck.gidl2 NEQ sim_config.sim_gidl2[0])
    {
      sim_clock     = SIMLOCK_LOCKED;
  		simlck.locks2 = (UBYTE) FldSet(simlck.locks2,clock,sim_clock);
 	 		sim_set_sim_lock (&simlck);
      return MFW_SIM_LOCKED;
    }

    /* 
     * check all digits */
		for (i=0; i<simlck.len_c_imsi; i++)
		{
			if (sim_check_imsi_digit(simlck.c_imsi[i], mfw_IMSI[i]) EQ FALSE)
				break;
		}

    /*
     * all digits okay
     */
		if (i EQ simlck.len_c_imsi)
			return MFW_SIM_ENABLE;

    /*
     * C-Lock has failed
     */
    sim_clock     = SIMLOCK_LOCKED;
		simlck.locks2 = (UBYTE) FldSet(simlck.locks2,clock,sim_clock);
		sim_set_sim_lock (&simlck);

    return MFW_SIM_LOCKED;
  }
  return MFW_SIM_FAILURE;
}

/*
+-----------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM               |
| STATE   : code                        ROUTINE : sim_get_simlock_count |
+-----------------------------------------------------------------------+

  PURPOSE : Request the count of SIMLOCK

*/

T_MFW sim_get_simlock_count(UBYTE *cnt)
{
  EF_SIMLCKEXT simlck;

  TRACE_FUNCTION("sim_get_simlock_count()");

  if (sim_get_sim_lock (&simlck) NEQ PCM_OK)
    return MFW_SIM_FAILURE;
  else
    *cnt = simlck.cnt;
  return MFW_SIM_SUCCESS;
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_pin_status     |
+--------------------------------------------------------------------+

  PURPOSE : Request PIN1/PIN2 status

*/

void sim_pin_status(T_MFW_SIM_PIN_STATUS *status)
{
  SHORT           pn1Cnt;
  SHORT           pn2Cnt;
  SHORT           pk1Cnt;
  SHORT           pk2Cnt;
  T_ACI_PVRF_STAT ps1;
  T_ACI_PVRF_STAT ps2;

  TRACE_FUNCTION("sim_pin_status()");

  status->stat = MFW_SIM_UNKNOWN;
  status->set  = MFW_SIM_UNKNOWN;
  if (qAT_PercentPVRF(CMD_SRC_LCL, &pn1Cnt, 
                      &pn2Cnt, &pk1Cnt, &pk2Cnt, &ps1, &ps2) == AT_CMPL)
  {
    switch (status->type)
    {
      case MFW_SIM_PIN1:
        status->stat = sim_cvtPINstatus(ps1, MFW_SIM_PIN1);
        status->set = pin1_set;
        break;
      case MFW_SIM_PIN2:
        status->stat = sim_cvtPINstatus(ps2, MFW_SIM_PIN2);
        status->set  = pin2_set;
        break;
    }
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_cvtPINstatus   |
+--------------------------------------------------------------------+

  PURPOSE :

*/

UBYTE sim_cvtPINstatus(T_ACI_PVRF_STAT ps, UBYTE type)
{
  TRACE_FUNCTION("sim_cvtPINstatus()");

  switch (ps)
  {
    case PVRF_STAT_NotRequired: 
      return MFW_SIM_NO_PIN;
    case PVRF_STAT_Required:
      if (type EQ MFW_SIM_PIN1) 
        return MFW_SIM_PIN_REQ;
      if (type EQ MFW_SIM_PIN2) 
        return MFW_SIM_PIN2_REQ;
      return MFW_SIM_UNKNOWN;
    default:                    
      return MFW_SIM_UNKNOWN;
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : simDecodeIMSI      |
+--------------------------------------------------------------------+

  PURPOSE : convert imsi (packed bcd to ASCIIZ; ->11.11)

*/

void simDecodeIMSI (UBYTE * imsi_field, 
                    UBYTE   imsi_c_field, 
                    UBYTE * imsi_extracted)
{
  UBYTE length;
  UBYTE i;
  UBYTE digit;

  TRACE_FUNCTION ("simDecodeImsi()");

  /*
   * calculate number of digits
   */
  length = (imsi_c_field-1)*2;

  /*
   * if odd number of digits add one
   */
  if (imsi_field[0] & 0x08)
    length++;

  /*
   * extract all digits
   */
  for (i = 0; i < length; i++)
  {
    digit = (i & 1) ?
        imsi_field[(i + 1) / 2] & 0x0f :
       (imsi_field[(i + 1) / 2] & 0xf0) >> 4;

#if defined (WIN32)
    {
      char buf[40];
      sprintf (buf, "DIGIT [%d] = %d",i, digit);
      TRACE_FUNCTION (buf);
    }
#endif
    if (i < LONG_NAME)
      imsi_extracted [i] = digit + 0x30;
    else
    {
      imsi_extracted [i] = 0;
      return;
    }
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_pin_ident      |
+--------------------------------------------------------------------+

  PURPOSE : handle mfw windows command

*/

void sim_pin_ident(UBYTE id)
{
  TRACE_FUNCTION("sim_pin_ident()");
  pin_ident = id;
}

/*
+-----------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)         MODULE  : MFW_SIM              |
| STATE   : code                         ROUTINE : sim_check_imsi_digit |
+-----------------------------------------------------------------------+

  PURPOSE : Check a IMSI digit

*/

T_MFW sim_check_imsi_digit(UBYTE pcm_imsi, UBYTE sim_imsi)
{
	UBYTE h;
	UBYTE l;

  TRACE_FUNCTION("sim_check_imsi_digit()");

	h = pcm_imsi >> 4 | 0x30;
	l = pcm_imsi & 0x0F | 0x30;

#if defined (WIN32)
  {
    char buf[40];
    sprintf (buf, "check %c shall be in the range [%c..%c]",
             sim_imsi, h, l);
    TRACE_FUNCTION (buf);
  }
#endif

	if (h > l)
		return FALSE;

	if ((sim_imsi < h) OR (sim_imsi > l))
		return FALSE;

	return TRUE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : simCommand         |
+--------------------------------------------------------------------+

  PURPOSE : handle mfw windows command

*/

static int simCommand (U32 cmd, void *h)
{
    switch (cmd)
    {
        case MfwCmdDelete:              /* delete me                */
            if (!h)
                return 0;
            sim_delete(h);
            return 1;
        default:
            break;
    }

    return 0;
}



/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_get_sim_lock   |
+--------------------------------------------------------------------+

  PURPOSE : Reads the SIM LOCK Record content from PCM

*/

#if defined (WIN32)
static const UBYTE sim_lock_table_1 [] =
{
  //
  // all locks enabled, wrong IMSI
  //
  0x55, 0x01,                // locks
  0x00,                      // unblock counter
  0x0F,                      // maximum attempt
  0x21, 0x43, 0x65, 0x87,    // P control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // N control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // NS control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // SP control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // C control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x0F,                      // length of IMSI
  0x22, 0x00, 0x22, 0x01,    // IMSI range definition
  0x23, 0x15, 0x22, 0x35,
  0x24, 0x25, 0x11, 0x22,
  0x46, 0x55, 0x66,   
  0x00,	0x00                 // Group Identifier
};

static const UBYTE sim_lock_table_2 [] =
{
  //
  // all locks enabled, IMSI ok
  //
  0x55, 0x01,                // locks
  0x00,                      // unblock counter
  0x0F,                      // maximum attempt
  0x21, 0x43, 0x65, 0x87,    // P control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // N control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // NS control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // SP control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // C control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x0D,                      // length of IMSI
  0x22, 0x66, 0x22, 0x00,    // IMSI range definition
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x00,	0x00                 // Group Identifier
};

static const UBYTE sim_lock_table_3 [] =
{
  //
  // all locks enabled, wrong IMSI, extended format
  //
  0x55, 0x01,                // locks
  0x00,                      // unblock counter
  0x0F,                      // maximum attempt
  0x21, 0x43, 0x65, 0x87,    // P control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // N control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // NS control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // SP control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // C control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x0F,                      // length of IMSI P-Lock
  0x22, 0x00, 0x22, 0x01,    // IMSI range definition P-Lock
  0x23, 0x15, 0x22, 0x35,
  0x24, 0x25, 0x11, 0x22,
  0x46, 0x55, 0x66,   
  0x0F,                      // length of IMSI SP-Lock
  0x22, 0x00, 0x22, 0x01,    // IMSI range definition SP-Lock
  0x23, 0x15, 0x22, 0x35,
  0x24, 0x25, 0x11, 0x22,
  0x46, 0x55, 0x66,   
  0x0F,                      // length of IMSI NS-Lock
  0x22, 0x00, 0x22, 0x01,    // IMSI range definition NS-Lock
  0x23, 0x15, 0x22, 0x35,
  0x24, 0x25, 0x11, 0x22,
  0x46, 0x55, 0x66,   
  0x0F,                      // length of IMSI C-Lock
  0x22, 0x00, 0x22, 0x01,    // IMSI range definition C-Lock
  0x23, 0x15, 0x22, 0x35,
  0x24, 0x25, 0x11, 0x22,
  0x46, 0x55, 0x66,   
  0x0F,                      // length of IMSI N-Lock
  0x22, 0x00, 0x22, 0x01,    // IMSI range definition N-Lock
  0x23, 0x15, 0x22, 0x35,
  0x24, 0x25, 0x11, 0x22,
  0x46, 0x55, 0x66,   
  0x0F,                      // length of IMSI U-Lock
  0x22, 0x00, 0x22, 0x01,    // IMSI range definition U-Lock
  0x23, 0x15, 0x22, 0x35,
  0x24, 0x25, 0x11, 0x22,
  0x46, 0x55, 0x66,   
  0x00,	0x00                 // Group Identifier
};

static const UBYTE sim_lock_table_4 [] =
{
  //
  // all locks enabled, IMSI ok, extended format
  //
  0x55, 0x01,                // locks
  0x00,                      // unblock counter
  0x0F,                      // maximum attempt
  0x21, 0x43, 0x65, 0x87,    // P control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // N control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // NS control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // SP control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // C control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x0D,                      // length of IMSI P-Lock 
  0x22, 0x66, 0x22, 0x00,    // IMSI range definition P-Lock
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x0D,                      // length of IMSI SP-Lock 
  0x22, 0x66, 0x22, 0x00,    // IMSI range definition SP-Lock
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x0D,                      // length of IMSI NS-Lock 
  0x22, 0x66, 0x22, 0x00,    // IMSI range definition NS-Lock
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x0D,                      // length of IMSI C-Lock 
  0x22, 0x66, 0x22, 0x00,    // IMSI range definition C-Lock
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x0D,                      // length of IMSI N-Lock 
  0x22, 0x66, 0x22, 0x00,    // IMSI range definition N-Lock
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x0D,                      // length of IMSI U-Lock 
  0x22, 0x66, 0x22, 0x00,    // IMSI range definition U-Lock
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x00,	0x00                 // Group Identifier
};

static const UBYTE sim_lock_table_5 [] =
{
  //
  // one lock enabled, wrong IMSI ok
  //
  0x01, 0x00,                // locks
  0x00,                      // unblock counter
  0x0F,                      // maximum attempt
  0x21, 0x43, 0x65, 0x87,    // P control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // N control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // NS control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // SP control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x43, 0x65, 0x87,    // C control key
  0xFF, 0xFF, 0xFF, 0xFF,
  0x0D,                      // length of IMSI
  0x22, 0x00, 0x22, 0x00,    // IMSI range definition
  0x11, 0x44, 0x77, 0x09,
  0x09, 0x09, 0x09, 0x09,
  0x09, 0x09, 0x09,   
  0x00,	0x00                 // Group Identifier
};

#endif

static UBYTE sim_get_sim_lock (EF_SIMLCKEXT * simlck)
{
  UBYTE version;
  UBYTE sim_lock_type = 0;

  TRACE_FUNCTION("sim_get_sim_lock()");

#if defined (WIN32)
  version = 0;

  switch (sim_lock_mode)
  {
    case 1:
      memcpy (simlck, sim_lock_table_1, SIZE_EF_SIMLCK);
      sim_lock_field = 1;
      sim_fill_sim_lock (simlck);
      break;
    case 2:
      memcpy (simlck, sim_lock_table_2, SIZE_EF_SIMLCK);
      sim_lock_field = 1;
      sim_fill_sim_lock (simlck);
      break;
    case 3:
      memcpy (simlck, sim_lock_table_3, SIZE_EF_SIMLCKEXT);
      sim_lock_field = 2;
      break;
    case 4:
      memcpy (simlck, sim_lock_table_4, SIZE_EF_SIMLCKEXT);
      sim_lock_field = 2;
      break;
    case 5:
      memcpy (simlck, sim_lock_table_5, SIZE_EF_SIMLCKEXT);
      sim_lock_field = 1;
      break;
    default:
      memset (simlck, 0, SIZE_EF_SIMLCKEXT);
      sim_lock_field = 2;
      break;
  }
  return PCM_OK;
#else

  if (sim_lock_field EQ NOT_PRESENT_8BIT)
  {
    if (pcm_ReadFile((UBYTE *) EF_SIMLCK_ID,
                     SIZE_EF_SIMLCK,
                     (UBYTE *) simlck,
                     &version) EQ PCM_OK)
    {
      sim_lock_field = 1;
      sim_fill_sim_lock (simlck);
      return PCM_OK;
    }
    if (pcm_ReadFile((UBYTE *) EF_SIMLCKEXT_ID,
                     SIZE_EF_SIMLCKEXT,
                     (UBYTE *) simlck,
                     &version) EQ PCM_OK)
    {
      sim_lock_field = 2;
      return PCM_OK;
    }
    return PCM_NVRAM_ACCS_FAIL;
  }

  if (sim_lock_field EQ 1)
  {
    if (pcm_ReadFile((UBYTE *) EF_SIMLCK_ID,
                     SIZE_EF_SIMLCK,
                     (UBYTE *) simlck,
                     &version) EQ PCM_OK)
    {
      sim_fill_sim_lock (simlck);
      return PCM_OK;
    }
  }

  if (sim_lock_field EQ 2)
  {
    if (pcm_ReadFile((UBYTE *) EF_SIMLCKEXT_ID,
                     SIZE_EF_SIMLCKEXT,
                     (UBYTE *) simlck,
                     &version) EQ PCM_OK)
    {
      return PCM_OK;
    }
  }
  return PCM_NVRAM_ACCS_FAIL;
#endif
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_get_sim_lock   |
+--------------------------------------------------------------------+

  PURPOSE : Reads the SIM LOCK Record content from PCM

*/

static void sim_set_sim_lock (EF_SIMLCKEXT * simlck)
{
  TRACE_FUNCTION("sim_set_sim_lock()");

  if (sim_lock_field EQ 1)
  {
    /*
     * set GDL1 and 2 on the expected location
     * => len_sp_imsi = gdl1, sp_imsi[0] = gdl2
     */
    simlck->len_sp_imsi = simlck->gidl1;
    simlck->sp_imsi [0] = simlck->gidl2;
    pcm_WriteFile((UBYTE *) EF_SIMLCK_ID,SIZE_EF_SIMLCK,
	  						  (UBYTE *) simlck);
  }
  else
    pcm_WriteFile((UBYTE *) EF_SIMLCKEXT_ID,SIZE_EF_SIMLCKEXT,
	  						  (UBYTE *) simlck);
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_fill_sim_lock  |
+--------------------------------------------------------------------+

  PURPOSE : Fills the extended SIM Lock record with defaults if
            only the simple SIM Lock Record is available.

*/

static void sim_fill_sim_lock (EF_SIMLCKEXT * simlck)
{
  TRACE_FUNCTION("sim_fill_sim_lock()");

  if (sim_lock_field EQ 1)
  {
    /*
     * PCM contains SIMLOCK record. Must be mapped to the internal
     * used SIMLOCKEXT record.
     *
     * gidl1, gidl2 to the end of record:
     */
    simlck->gidl1 = simlck->len_sp_imsi;
    simlck->gidl2 = simlck->sp_imsi [0];
    /*
     * IMSI must be copied for the other locks
     * N-Lock   digits 1..5, rest filled with 0x09 to suppress compare
     * SP-Lock  digits 1..5, rest filled with 0x09 to suppress compare
     * NS-Lock  digits 1..7, rest filled with 0x09 to suppress compare     
     * C-Lock   digits 1..5, rest filled with 0x09 to suppress compare
     */
    memset (simlck->n_imsi, 0x09, 15);
    memcpy (simlck->n_imsi, simlck->p_imsi, 5);
    simlck->len_n_imsi = 5;
    memset (simlck->sp_imsi, 0x09, 15);
    memcpy (simlck->sp_imsi, simlck->p_imsi, 5);
    simlck->len_ns_imsi = 5;
    memset (simlck->ns_imsi, 0x09, 15);
    memcpy (simlck->ns_imsi, simlck->p_imsi, 7);
    simlck->len_ns_imsi = 7;
    memset (simlck->c_imsi, 0x09, 15);
    memcpy (simlck->c_imsi, simlck->p_imsi, 5);
    simlck->len_c_imsi = 5;
    /*
     * initialise unblock imsi so that it never will fit
     */
    simlck->len_u_imsi = 0;
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)     MODULE  : MFW_SIM               |
| STATE   : code                     ROUTINE : sim_check_unblock_sim |
+--------------------------------------------------------------------+

  PURPOSE : Checks the IMSI against a stored unblock SIM. If the
            check is positive, the unlock attempt counter will 
            be resetted.
            
*/

static void sim_check_unblock_sim (EF_SIMLCKEXT * simlck)
{
  UBYTE i;

  TRACE_FUNCTION("sim_check_unblock_sim()");

  if (sim_get_sim_lock (simlck) EQ PCM_OK)
  {
    if (simlck->len_u_imsi EQ 0)
      return;

    /* 
     * check all digits */
	  for (i=0; i<simlck->len_u_imsi; i++)
    {
  	  if (sim_check_imsi_digit(simlck->u_imsi[i], mfw_IMSI[i]) EQ FALSE)
		    break;
    }

    /*
     * all digits okay, then reset counter and nothing else
     */
	  if (i EQ simlck->len_u_imsi)
    {
  	  simlck->cnt = 0;
	    sim_set_sim_lock (simlck);
    }
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)     MODULE  : MFW_SIM               |
| STATE   : code                     ROUTINE : sim_simlock_ok        |
+--------------------------------------------------------------------+

  PURPOSE : The function checks whether the SIM LOCK is active or not.
            
*/

UBYTE sim_simlock_ok (void)
{
  if (sim_nslock EQ SIMLOCK_BLOCKED OR
      sim_nslock EQ SIMLOCK_LOCKED)
    return FALSE;

  if (sim_plock EQ SIMLOCK_BLOCKED OR
      sim_plock EQ SIMLOCK_LOCKED)
    return FALSE;

  if (sim_splock EQ SIMLOCK_BLOCKED OR
      sim_splock EQ SIMLOCK_LOCKED)
    return FALSE;

  if (sim_nlock EQ SIMLOCK_BLOCKED OR
      sim_nlock EQ SIMLOCK_LOCKED)
    return FALSE;

  if (sim_clock EQ SIMLOCK_BLOCKED OR
      sim_clock EQ SIMLOCK_LOCKED)
    return FALSE;

  return TRUE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_SIM            |
| STATE   : code                        ROUTINE : sim_get_imsi       |
+--------------------------------------------------------------------+

  PURPOSE : Request IMSI number in SIM card

*/

UBYTE * sim_get_imsi (void)
{
  return mfw_IMSI;
}

/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)   MODULE  : MFW_SIM                  |
| STATE   : code                   ROUTINE : sim_mmi_update_parameter |
+---------------------------------------------------------------------+

  PURPOSE : MMI relevant parameters from the SIM card

*/

void sim_mmi_update_parameter(T_SIM_ACTIVATE_IND *sim_act_ind)
{
  TRACE_FUNCTION("sim_mmi_update_parameter()");

  memcpy( sim_config.pref_lang, sim_act_ind->pref_lang, 5);
}

#ifdef SIM_TOOLKIT
/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)   MODULE  : MFW_SIM                  |
| STATE   : code                   ROUTINE : sim_sat_file_update      |
+---------------------------------------------------------------------+

  PURPOSE : SIM file change indication

*/

void sim_sat_file_update(USHORT dataId)
{
  TRACE_FUNCTION("sim_sat_file_update()");

  sat_update = TRUE;
  switch (dataId)
  {
    case SIM_SST:
      sim_read_sim(SIM_SST, NOT_PRESENT_8BIT, 10);
      break;
    case SIM_GID1:
      sim_read_sim(SIM_GID1, NOT_PRESENT_8BIT, 5);
      break;
    case SIM_GID2:
      sim_read_sim(SIM_GID2, NOT_PRESENT_8BIT, 5);
      break;
    default:
      break;
  }
}
#endif

/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)   MODULE  : MFW_SIM                  |
| STATE   : code                   ROUTINE : sim_read_sst_cnf         |
+---------------------------------------------------------------------+

  PURPOSE : SIM file change indication

*/

void sim_read_sst_cnf (SHORT error, UBYTE *data)
{
  TRACE_FUNCTION("sim_read_sst_cnf()");

  if (error EQ SIM_NO_ERROR)
    memcpy(sim_service_table, data, sizeof(sim_service_table));
  else
    TRACE_EVENT("SST read error");

#ifdef SIM_TOOLKIT
  if (sat_update)
  {
    sat_update = FALSE;
    satUpdateFiles ( TRUE, SIM_SST );
  }
#endif
}