view src/aci2/mfw/mfw_sim.~c @ 478:5e39123540e6

hybrid fw: Openmoko-mimicking AT@BAND command implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 14 Jun 2018 06:04:54 +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
}