diff src/cs/drivers/drv_app/sim/sim.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children b37e6c916df1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/drivers/drv_app/sim/sim.c	Fri Oct 16 06:23:26 2020 +0000
@@ -0,0 +1,3192 @@
+/*
+ * SIM.C
+ *
+ * Pole Star SIM
+ *                 
+ * Target : ARM
+ *
+ *
+ * SIM card driver. This module contents all functions 
+ * included in specifications GSM 11.11 V4.10
+ *
+ *
+ * Copyright (c) Texas Instruments 1995-1997
+ *
+ */
+                                        
+#define SIM_C   1
+
+#ifndef _WINDOWS
+	#include "l1sw.cfg" 
+	#include "chipset.cfg" 
+#endif
+
+#include "main/sys_types.h"
+
+#include "memif/mem.h"
+
+//#include "assert.h"
+#if (CHIPSET == 12)
+    #include "inth/sys_inth.h"
+#else
+    #include "inth/iq.h"
+#endif
+#include "sim.h"
+#include <string.h>
+#include "armio/armio.h"
+#include "ind_os.h"
+#include "abb/abb.h"                     //controls level shifter of ABB
+#include "ffs/ffs_api.h"		 /* FreeCalypso addition */
+
+
+//current voltage mode 3V or 5V, or 1.8V
+SYS_UWORD8            CurrentVolt;
+
+/* FreeCalypso addition */
+SYS_UWORD8 SIM_allow_speed_enhancement = 1;
+
+
+
+#ifdef SIM_DEBUG_TRACE
+
+#ifdef SIM_RETRY
+/* one byte more to trace the number of retry for each functions */
+#define SIM_DBG_NULL 5
+#else
+/* size of buffer tracing the reception of NULL byte */
+#define SIM_DBG_NULL 4
+#endif
+
+/* working buffer for NULL BYTE and number of RETRY */
+SYS_UWORD8  SIM_dbg_null[SIM_DBG_NULL];
+/* size of buffer tracing the chronology of calls */
+#define SIM_DBG_CMD 7500
+/* working buffer for chronology calls */
+SYS_UWORD8  SIM_dbg_cmd[SIM_DBG_CMD];
+/* index for positionning in working buffer for chronology calls */
+SYS_UWORD16  SIM_dbg_cmd_cmpt;       
+/* working variable to calculate the TDMA ecart */
+SYS_UWORD16 SIM_dbg_tdma_diff;
+/* working variable to store the maximum TDMA frame between two characters */
+SYS_UWORD16 SIM_dbg_max_interchardelay;
+/* working variable used in each L2/L3 access function */
+SYS_UWORD8 SIM_dbg_tmp[10];
+/* internal function due to factorization of use of traces */
+void SIM_dbg_write_trace(SYS_UWORD8 *ptr, SYS_UWORD16 len);
+
+#endif
+
+#ifdef SIM_RETRY
+/* number of retry */
+#define	NUM_SIM_RETRIES	10
+/* Add variables to support sim retry */
+SYS_UWORD8 SimRetries;
+#endif
+
+
+
+
+
+
+/*
+ * Low level routines  : mapped to hardware
+ *    SIM_WriteBuffer
+ *    SIM_Command
+ *    SIM_Reset
+ *    
+ */
+
+
+
+/*
+ * SIM_WriteBuffer
+ *
+ * Write n bytes to SIM card in interrupt mode:
+ *   return the line, write first byte and let interrupt handler do the rest
+ * return the line, write first byte and let interrupt handler do the rest
+ *
+ * Parameters : 
+ *   SIM_PORT *p : buffer for received chars
+ *   offset      : starting point for reading data.
+ *   n           : number of chars to read.
+ */
+void SIM_WriteBuffer(SIM_PORT *p, SYS_UWORD16 offset, SYS_UWORD16 n)
+{
+   unsigned volatile i;
+
+   // Set write direction
+   p->conf1 |= SIM_CONF1_TXRX;
+   p->c->conf1 = p->conf1;
+
+   p->SWcount  = 0;
+   p->rx_index = 0;
+   p->expected_data = 0;
+
+   p->xOut = p->xbuf + offset;
+   p->xIn  = p->xbuf + offset + n;
+
+   if ((p->xIn - p->xOut) == 1)        //if only one char is transmitted
+   {                                   //need to wait a minimum of 1 ETU
+        ind_os_sleep (1);                  //for IO line to stay in TX mode
+   } 
+   // Write first byte 
+   p->c->tx = *(p->xOut);              // transmit
+
+   if ((p->xIn - p->xOut) == 1)        //if only one char to transmit
+   {                                   // return the direction to rx
+        p->conf1 &= ~SIM_CONF1_TXRX;   //to be able to receive ACK char
+        p->c->conf1 = p->conf1;        
+
+   }
+}
+
+/*
+ * SIM_Result
+ *    
+ * Parameters : SIM port, buffer for received chars, pointer to receive size
+ * 
+ * Return the result code (SW1/SW2) at the end of the string
+ */
+SYS_UWORD16 SIM_Result(SIM_PORT *p, SYS_UWORD8 *rP, SYS_UWORD16 *lenP, SYS_UWORD8 offset)
+{
+   SYS_UWORD8 sw1, sw2;
+   SYS_UWORD8 verdict;
+   SYS_UWORD16 len;
+   
+   // Check if all characters were transmitted
+   if (p->xIn - 1 != p->xOut)
+      return (SIM_ERR_XMIT);
+   
+   len = p->rx_index;
+   *lenP = len - offset;
+   if ((*lenP == 0) && (p->apdu_ans_length == 256))
+		*lenP = 256;
+
+   if (p->expected_data == 256)
+   {
+       verdict = SIM_Memcpy(rP, ((p->rbuf) + offset), 256 - offset);
+       if (verdict != 0)
+       { 
+           return (verdict);
+       }
+   }
+   else if ((len != 0) && (len >= offset))
+   {
+       verdict = SIM_Memcpy(rP, ((p->rbuf) + offset), len - offset);
+       if (verdict != 0)
+       {
+           return (verdict);
+       }
+   }
+   
+   // change to remove SW1 and SW2 bytes from the receive buffer of data 
+   sw1 = p->rSW12[0];
+   sw2 = p->rSW12[1];
+
+   return((sw1 << 8) | sw2);
+}
+
+
+
+
+
+/*
+ * SIM_Command_base
+ *
+ * Perform a command with the SIM T=0 protocol
+ *
+ * Arguments : pointer to SIM port structure
+ *             number of characters above 5
+ *             expected command time in TDMA
+ *
+ * Returns an error code :
+ *             SIM_ERR_READ : no answer from the card to a command
+ *             SIM_ERR_LEN  : the answer is not corresponding to a
+ *                            correct answer of T=0 protocol
+ * 06/11/2002	JYT
+ *		Modified to be base command function. New SIM_Command() created to call it 
+ * 		with wrapper. Created to manage retries on Internals errors of the driver.
+ */
+
+SYS_UWORD16 SIM_Command_Base(SIM_PORT *p, SYS_UWORD16 n, SYS_UWORD8 *dP, SYS_UWORD16 *lP)
+{
+    SYS_UWORD16  res;
+    SYS_UWORD8    err;
+    SYS_UWORD8    ins;
+    SYS_UWORD8    nack;
+    SYS_UWORD8    nack1;
+    SYS_UWORD16  offset;
+
+    if (SIM_sleep_status == SIM_SLEEP_DESACT)
+    {   //freeze the timer
+        status_os_sim = NU_Control_Timer (&SIM_timer,  NU_DISABLE_TIMER);
+    }
+    else if (SIM_sleep_status == SIM_SLEEP_ACT)
+    {   //get out sleep mode
+        status_os_sim = NU_Control_Timer (&SIM_timer,  NU_DISABLE_TIMER);
+        SIM_SleepMode_Out (p);   //get up SIM card of sleep mode before executing the command
+    }
+
+    SIM_WriteBuffer(p, 0, 5);
+
+    //adaptative driver
+
+    if (n > 0)          //need to send data to the card, TX mode
+    {
+        offset = 0;
+        // protocol T=0 returns a acknowledge char which is
+        //     ins or (ins+1)   : transmit the rest of the command in one time
+        //     ~ins or ~(ins+1) : transmit the rest of the command char by char
+        ins   = p->xbuf[1] & p->hw_mask;
+        nack  = (~p->xbuf[1]) & p->hw_mask;;
+
+        p->moderx = 6;  //mode of wait for ACK char
+
+NEXT_CHAR_PROC:
+
+        if (err = SIM_Waitforchars(p, p->etu9600))
+        {
+            if ((SIM_sleep_status == SIM_SLEEP_DESACT) || (SIM_sleep_status == SIM_SLEEP_ACT))
+            {   //enable to count 2.5s before entering in sleep mode
+                status_os_sim = NU_Reset_Timer (&SIM_timer, SIM_SleepMode_In,
+                                                SIM_SLEEP_WAITING_TIME,
+                                                0, NU_ENABLE_TIMER);
+            }
+            return (err);
+        }
+
+        if (p->moderx == 5)     //return SW1/SW2
+        {
+            res = SIM_Result(p, dP, lP, 0);
+
+            if ((SIM_sleep_status == SIM_SLEEP_DESACT) || (SIM_sleep_status == SIM_SLEEP_ACT))
+            {   //enable to count 2.5s before entering in sleep mode
+                status_os_sim = NU_Reset_Timer (&SIM_timer, SIM_SleepMode_In,
+                                                SIM_SLEEP_WAITING_TIME,
+                                                0, NU_ENABLE_TIMER);
+            }
+
+            return(res);
+        }
+        else if ((p->ack & p->hw_mask) == ins)
+        {
+        // Write the rest of the command if needed
+        // if more than 5 characters, the ack character will disappear
+
+            SIM_WriteBuffer(p, 5 + offset, n - offset);
+        }
+        // special transmission mode if ACK = ~INS or ~(INS + 1).
+        // refer to ISO/CEI 7816-3 [8.2.2]
+        // need to send char by char
+        else if ((p->ack & p->hw_mask) == nack)
+        {
+            SIM_WriteBuffer(p, 5 + offset, 1);
+            offset++;
+            goto NEXT_CHAR_PROC;
+        }
+
+        p->moderx = 5;
+        if (err = SIM_Waitforchars (p, p->etu9600))  //wait SW1 / SW2
+        {
+            if ((SIM_sleep_status == SIM_SLEEP_DESACT) || (SIM_sleep_status == SIM_SLEEP_ACT))
+            {   //enable to count 2.5s before entering in sleep mode
+                status_os_sim = NU_Reset_Timer (&SIM_timer, SIM_SleepMode_In,
+                                                SIM_SLEEP_WAITING_TIME,
+                                                0, NU_ENABLE_TIMER);
+            }
+            return (err);
+        }
+
+    }
+    else                //receive mode
+    {
+        if (err = SIM_WaitReception(p))  //wait for next procedure character
+        {
+            if ((SIM_sleep_status == SIM_SLEEP_DESACT) || (SIM_sleep_status == SIM_SLEEP_ACT))
+            {   //enable to count 2.5s before entering in sleep mode
+                status_os_sim = NU_Reset_Timer (&SIM_timer, SIM_SleepMode_In,
+                                                SIM_SLEEP_WAITING_TIME,
+                                                0, NU_ENABLE_TIMER);
+            }
+            return (err);
+        }
+    }
+
+    res = SIM_Result(p, dP, lP, 0);
+
+            if ((SIM_sleep_status == SIM_SLEEP_DESACT) || (SIM_sleep_status == SIM_SLEEP_ACT))
+    {   //enable to count 2.5s before entering in sleep mode
+        status_os_sim = NU_Reset_Timer (&SIM_timer, SIM_SleepMode_In,
+                                                SIM_SLEEP_WAITING_TIME,
+                                                0, NU_ENABLE_TIMER);
+    }
+
+    return(res);
+}
+
+
+/* Main function to manage the retry mechanism */
+SYS_UWORD16 SIM_Command(SIM_PORT *p, SYS_UWORD16 n, SYS_UWORD8 *dP, SYS_UWORD16 *lP) {   
+	int res;
+
+#ifdef SIM_DEBUG_TRACE
+	memset(SIM_dbg_null, 0x00, SIM_DBG_NULL);
+	SIM_dbg_tdma_diff = 0;
+#endif
+
+	// Issue initial SIM_Command() call
+    res = SIM_Command_Base(p, n, dP, lP);
+    /* Change from to 10 to 15 for specific SIM card (Racal) */
+
+#ifdef SIM_RETRY
+    // While there is an error then retry NUM_SIM_RETRIES times
+	while ((res & 0xFF00) == 0)	{	// Reissue command
+		p->errorSIM = 0;
+		if(++SimRetries > NUM_SIM_RETRIES) {	// return special retry failure
+		   	res = SIM_ERR_RETRY_FAILURE;
+		   	break;
+		}
+	    res = SIM_Command_Base(p, n, dP, lP);
+	}
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_null[SIM_DBG_NULL-1] = SimRetries;
+#endif
+
+	SimRetries = 0;
+#endif
+
+    return(res);
+}
+
+
+
+
+
+                                
+/*
+ * SIM_ByteReverse
+ *
+ * Reverse a byte, both up/down (1 <> 0) and left/right (0001 <> 1000)
+ * 
+ */
+SYS_UWORD8 SIM_ByteReverse(SYS_UWORD8 b)
+{
+    SYS_UWORD8 bh, bl;
+    int i;
+    const SYS_UWORD8 Reverse[] = {0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE, 
+                                    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF };
+
+    // Up/Down
+    b = ~ b;
+
+    // left / right (by nibble)
+    bh = (b >> 4) & 0xF;
+    bl = b & 0xF;
+      
+    b = (Reverse[bl]) << 4 | Reverse[bh];
+    return(b);
+   
+}
+
+/*
+ * SIM_TxParityErrors
+ *
+ * return number of transmit parity errors occured since the last reset
+ * of the SIM card
+ *
+ */
+SYS_UWORD16 SIM_TxParityErrors(void)
+{
+    SIM_PORT *p;
+
+    p= &(Sim[0]);
+
+    return(p->txParityErr);
+}
+
+
+/*
+ * SIM_Reset
+ *
+ * Reset SIM card 
+ * Call-back SIM insert if successful
+ * or SIM remove otherwise
+ *
+ * Returns 0 for success, or
+ *         SIM_ERR_NOCARD : no card
+ *         SIM_ERR_NATR   : no answer to reset
+ *         SIM_ERR_NOINT  : no 
+ *         SIM_ERR_READ   : unknown data return by the card
+ *         SIM_ERR_CARDREJECT : card not accepted
+ *
+ * 29/01/02, JYT, adding of low voltage managment for IOTA device
+ * 06/10/03, JYT, Split of Reset to handle Restart
+ */ 
+SYS_UWORD16 SIM_Reset(SIM_CARD *cP)
+{
+	return(SIM_Reset_Restart_Internal(cP, 1));
+}
+
+
+
+
+
+
+
+/*
+ * SIM_Restart
+ *
+ * Restart SIM card 
+ *
+ * Returns 0 for success, or
+ *         SIM_ERR_NOCARD : no card
+ *         SIM_ERR_NATR   : no answer to reset
+ *         SIM_ERR_NOINT  : no 
+ *         SIM_ERR_READ   : unknown data return by the card
+ *         SIM_ERR_CARDREJECT : card not accepted
+ *
+ * 06/10/03, JYT, Split of Reset to handle Restart
+ */ 
+SYS_UWORD16 SIM_Restart(SIM_CARD *cP)
+{
+	return(SIM_Reset_Restart_Internal(cP, 0));
+}
+
+
+/*
+ * SIM_Reset_Restart_Internal
+ *
+ * Reset SIM card 
+ * Call-back SIM insert if successful
+ * or SIM remove otherwise
+ *							  
+ * Returns 0 for success, or
+ *         SIM_ERR_NOCARD : no card
+ *         SIM_ERR_NATR   : no answer to reset
+ *         SIM_ERR_NOINT  : no 
+ *         SIM_ERR_READ   : unknown data return by the card
+ *         SIM_ERR_CARDREJECT : card not accepted
+ *
+ * 29/01/02, JYT, adding of low voltage managment for IOTA device
+ * 06/10/03, JYT, Split of Reset to handle Restart, ResetFlag added.
+ */ 
+SYS_UWORD16 SIM_Reset_Restart_Internal(SIM_CARD *cP, SYS_UWORD8 ResetFlag)
+{
+    SIM_PORT        *p;
+    unsigned int    ATR_Attempt;
+    SYS_UWORD8      BackValue;
+    SYS_UWORD8      Result_ATR;
+
+#ifdef SIM_DEBUG_TRACE
+	memset(SIM_dbg_null, 0x00, SIM_DBG_NULL);
+	SIM_dbg_cmd_cmpt = 0;
+	memset(SIM_dbg_cmd, 0x00, SIM_DBG_CMD);
+#endif
+
+    // Initialize pointers 
+    p = &(Sim[0]);
+
+// begin of JYT modifications
+    if ( (BackValue = SIM_StartVolt(ResetFlag)) != SIM_OK)
+       return((SYS_UWORD16)BackValue);
+// end of JYT modifications
+
+    p->etu9600    = 867; // old = 239, increase of 363%
+    p->etu400     = 20;
+    p->hw_mask    = MASK_INS;
+
+    ATR_Attempt      = 1;
+
+COLD_RESET:
+
+    p->SWcount       = 0;
+    p->Freq_Algo     = 0;
+    p->PTS_Try       = 0;            //use to calculate how many PTS try were already done
+    
+    // Initialize pointers 
+    p->xIn   = p->xOut = p->xbuf;
+    p->rx_index        = 0;
+    p->errorSIM        = 0;
+    p->moderx          = 0;
+    p->null_received   = 0;
+
+    BackValue = SIM_ManualStart(p);
+    if (BackValue != 0)
+        return ((SYS_UWORD16)BackValue);
+    
+      
+    p->c->conf1 = p->conf1 &= ~SIM_CONF1_BYPASS;      //switch to automatic mode             
+
+//#else //SW_WRK_AROUND_H_S == 0 // Automatic procedure -> fails with test 27.11.2.1
+//
+//                                  // Mask all interrupts
+//    p->c->maskit = SIM_MASK_NATR | SIM_MASK_WT | SIM_MASK_OV | 
+//                   SIM_MASK_TX | SIM_MASK_RX | SIM_MASK_CD;
+//
+//
+//   IQ_Unmask (IQ_SIM);           // Unmask interrupt controller
+//
+//
+//    p->c->cmd = (p->c->cmd & MASK_CMD) | SIM_CMD_STOP;
+//    ind_os_sleep(1);
+//                      
+//    p->c->cmd = (p->c->cmd & MASK_CMD) | SIM_CMD_SWRST;    // Set START bit and wait a while
+//    ind_os_sleep(1);
+//                                  // Unmask all sources of interrupts except WT, OV, and NATR
+//    p->c->maskit = SIM_MASK_OV | SIM_MASK_WT | SIM_MASK_NATR;
+//
+//                                  // Set Configuration bits
+//    p->c->conf1     = p->conf1 = SIM_CONF1_SRSTLEV | SIM_CONF1_SCLKEN;
+//    p->c->conf2  = 0x0940;
+//
+//        //enable VCC
+//        #if(ANLG_FAM == 1)
+//          SPIABB_wa_VRPC (SPIRead_ABB_Register (PAGE1,VRPCCTRL1) | MODE_ENA_VCC);
+//        #elif(ANLG_FAM == 2)
+//          SPIABB_wa_VRPC (SPIRead_ABB_Register (PAGE1,VRPCSIM) | MODE_ENA_VCC);
+//        #endif
+//    p->c->cmd = (p->c->cmd & MASK_CMD) | SIM_CMD_START;
+//
+//#endif 
+
+/*-----------------------------------------------------------*/
+
+    while (p->PTS_Try != 5)
+    {
+        while (ATR_Attempt != 0)
+        {
+            // Treat ATR response
+            BackValue = SIM_ATRdynamictreatement (p, cP);
+
+            if (BackValue == SIM_ERR_NOCARD)
+            {
+                 SIM_PowerOff ();
+                 return (SIM_ERR_NOCARD);
+            }
+            // ATR received but wrong characters value
+            // Comply with Test 27.11.2.4.5 and Test 27.11.1.3
+            else if (BackValue == SIM_ERR_CARDREJECT)            
+                {
+                if (ATR_Attempt >= 3)
+            {
+                    SIM_PowerOff ();
+                    return ((SYS_UWORD16)BackValue);
+            }
+
+                ATR_Attempt++;
+                SIM_WARMReset(p);    // assert a reset during at least 400 ETU
+        }
+            else if (BackValue != 0) //SIM_ERR_WAIT           
+        {
+                if (ATR_Attempt == 3)
+                {    // switch to 5V (ANALOG1) or 3V (ANALOG2) if card send wrong ATR 3 consecutive times
+                     // Apply 3 consecutive resets at 5V (ANALOG1) or 3V (ANALOG2)
+                     // fix prb for old chinese card not GSM compliant   
+
+                     if ((BackValue = SIM_SwitchVolt(ResetFlag)) != SIM_OK) 
+                     {
+                     	// SIM cannot be supplied at 3V (ANALOG2), because of an Hardware failure
+                     	SIM_PowerOff ();
+                        return((SYS_UWORD16)BackValue);
+                     }   
+                     
+                     ATR_Attempt++;  
+                     goto COLD_RESET;  
+                }
+                if (ATR_Attempt >= 6) 
+                {
+                    SIM_PowerOff ();
+                    return ((SYS_UWORD16)BackValue);
+                }
+
+                ATR_Attempt++;
+                SIM_WARMReset(p);    // assert a reset during at least 400 ETU
+            }
+            
+            else
+            {
+                ATR_Attempt = 0;    
+            }
+        }
+/*-----------------------------------------------------------*/
+// PTS procedure
+        BackValue = SIM_PTSprocedure(cP,p);      //assert PTS if needed
+//        need upgrade with FIFO use to avoid CPU overloading
+              
+        if (BackValue)
+        {
+            if (BackValue == SIM_ERR_CARDREJECT)
+            {
+                SIM_PowerOff ();      //must be done by protocol stack
+                return (SIM_ERR_CARDREJECT);
+            }
+            if (p->PTS_Try <= 4)     //else error treatement  
+            {
+                SIM_WARMReset(p);    // assert a reset during at least 400 ETU
+            }            
+        }
+        else
+        {
+            p->PTS_Try = 5;
+        }
+    }
+/*-----------------------------------------------------------*/
+
+  //interpret SIM coding concerning SIM supply voltage
+
+    if (SIM_GetFileCharacteristics(p))
+    {
+#if ((SIM_TYPE == SIM_TYPE_3V) || (SIM_TYPE == SIM_TYPE_1_8V))
+        SIM_PowerOff();      // Needed for tests 27.17.1.5.1 and 27.17.1.5.5
+#endif
+        return (SIM_ERR_READ);
+    }
+
+   // JYT, certainly unused because of previous test
+    if(p->errorSIM)
+    {
+      return(p->errorSIM);
+    }
+
+    if ((p->FileC & SIM_MASK_INFO_VOLT) == SIM_5V)
+    {
+#if ((SIM_TYPE == SIM_TYPE_3V ) || (SIM_TYPE == SIM_TYPE_1_8_3V) || (SIM_TYPE == SIM_TYPE_1_8V))
+        SIM_PowerOff ();                 // required by ETSI if 5V only card is detected and 3V only ME chosen
+        return (SIM_ERR_CARDREJECT);     // Test 27.17.1.5.2    
+#elif (SIM_TYPE == SIM_TYPE_3_5V)  
+        if (CurrentVolt == SIM_3V) //if 5V only SIM present -> the ME may switch to 5V operation
+        {
+            if ((BackValue = SIM_SwitchVolt(ResetFlag)) != SIM_OK) // switch to 5V
+            {
+               SIM_PowerOff ();
+               return ((SYS_UWORD16)BackValue);
+            }	
+            ATR_Attempt      = 1;
+            goto COLD_RESET;            // Test 27.17.1.5.3 
+        }
+#endif              
+    }
+    else 
+    {
+       if ((p->FileC & SIM_MASK_INFO_VOLT) == SIM_3V)
+       {
+#if (SIM_TYPE == SIM_TYPE_1_8V)
+        SIM_PowerOff ();                 // required by ETSI if 3V only card is detected and 1.8V only ME chosen
+        return (SIM_ERR_CARDREJECT);     // Test 27.17.1.5.2    
+#elif (SIM_TYPE == SIM_TYPE_1_8_3V)  
+        if (CurrentVolt == SIM_1_8V) //if 3V only SIM present -> the ME may switch to 3V operation
+        {
+            if ((BackValue = SIM_SwitchVolt(ResetFlag)) != SIM_OK) // switch to 3V
+            {
+               SIM_PowerOff ();
+               return ((SYS_UWORD16)BackValue);
+            }	
+            ATR_Attempt      = 1;
+            goto COLD_RESET;            // Test 27.17.1.5.3 
+        }
+#endif                     	
+       }
+       else 
+       {
+          if ((p->FileC & SIM_MASK_INFO_VOLT) == SIM_1_8V)
+          {
+#if (SIM_TYPE == SIM_TYPE_5V)
+              SIM_PowerOff ();                 // required by ETSI if 5V only card is detected and 3V only ME chosen
+              return (SIM_ERR_CARDREJECT);     // Test 27.17.1.5.2    
+#endif                        	
+          }
+          else 
+          {
+       	      // future class of sim card voltage !!!!!! never use it
+       	      SIM_PowerOff ();                 // Rec. 11.18
+              return (SIM_ERR_CARDREJECT);     
+          }          
+       }
+    }      
+
+    SIM_Interpret_FileCharacteristics(p);      //find which frequency (13/4 or 13/8 Mhz) 
+
+    if(p->errorSIM)
+    {
+      return(p->errorSIM);
+    }
+
+    status_os_sim = NU_Control_Timer (&SIM_timer,  NU_ENABLE_TIMER);
+    //enable starting of the os timer for sleep mode
+    if (ResetFlag) {
+    if (p->InsertFunc != NULL)
+       (p->InsertFunc)(cP);   
+	}
+
+     return(0);
+}
+
+
+
+
+
+
+
+
+
+
+
+/* SIM manual start
+*
+*  purpose : manage manual start of the SIM interface
+*  input   : pointer on sim structure SIM_PORT
+*  output  : none
+*/
+
+SYS_UWORD16 SIM_ManualStart (SIM_PORT *p)
+{
+    volatile int             i;
+
+//!!
+    p->c->conf1 = p->conf1 = 0x8004;   //set conf1 to automatic mode SIO low
+    //enable sim interface clock module
+    p->c->cmd = SIM_CMD_CLKEN;    
+
+//#if (SW_WRK_AROUND_H_S == 1)
+
+    // Mask all interrupts
+    p->c->maskit = SIM_MASK_NATR | SIM_MASK_WT | SIM_MASK_OV | 
+           SIM_MASK_TX | SIM_MASK_RX | SIM_MASK_CD;
+
+    // Unmask interrupt controller
+    IQ_Unmask (IQ_SIM);
+
+    p->c->cmd = (p->c->cmd & MASK_CMD) | SIM_CMD_STOP;
+    ind_os_sleep (4);                           //wait 5 TDMA due to SVCC falling down duration 
+
+    p->c->cmd = (p->c->cmd & MASK_CMD) | SIM_CMD_SWRST;
+    ind_os_sleep (1);                           //wait 5 TDMA due to SVCC falling down duration 
+
+
+    p->c->conf2  = 0x0940;
+    
+    i = p->c->it;
+    // Unmask all sources of interrupts except WT and OV and NATR
+    p->c->maskit = SIM_MASK_WT | SIM_MASK_OV | SIM_MASK_NATR;
+
+
+    //enter in manual mode to start the ATR sequence
+    p->c->conf1 = p->conf1 |= SIM_CONF1_BYPASS;
+    ind_os_sleep(1);
+
+    p->c->conf1 = p->conf1 |= SIM_CONF1_SVCCLEV;
+    ind_os_sleep(1);
+
+    #if(ANLG_FAM == 1) 
+      //set OMEGA to 3V mode
+      //enable VCC
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCCTRL1) | MODE_ENA_SIMLDOEN);
+      ind_os_sleep(1);
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCCTRL1) | MODE_ENA_SIMEN);
+      ind_os_sleep(1);
+    #elif(ANLG_FAM == 2) 
+      //set IOTA to 3V mode
+      //enable VCC
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCSIM) | MODE_ENA_SIMEN);
+      ind_os_sleep(1);
+    #elif(ANLG_FAM == 3)
+      //set SYREN to 3V mode
+      //enable VCC
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCSIMR) | MODE_ENA_SIMEN);
+      ind_os_sleep(1);
+    #endif
+
+    p->c->conf1 = p->conf1 &= ~SIM_CONF1_SIOLOW;
+
+    ind_os_sleep(1);
+
+    p->c->conf1 = p->conf1 |= SIM_CONF1_SCLKEN;
+
+    p->c->conf1 = p->conf1 &= ~SIM_CONF1_TXRX; //set to receive mode
+
+
+    if(p->errorSIM)                       //check for card detection
+    {
+        return(p->errorSIM);
+    }
+
+    i = 0;
+    while ((p->rx_index == 0) && (i < 3))       //wait 40000*Tsclk
+    {
+        ind_os_sleep (1);
+        i++;
+    }        
+      
+    if ((p->rx_index == 0) && (i >= 3))         //external reset card ATR treatement
+    {
+        i = 0;
+
+        p->c->conf1 = p->conf1 |= SIM_CONF1_SRSTLEV;//set reset level to high level
+
+        while ((p->rx_index == 0) && (i < 3))   //wait 40000*Tsclk
+        {
+            ind_os_sleep (1);
+            i++;
+        }
+    }
+
+    return (0);
+}
+ 
+/* SIM manual stop
+*
+*  purpose : manage manual start of the SIM interface
+*  input   : pointer on sim structure SIM_PORT
+*  output  : none
+*/
+
+void SIM_ManualStop (SIM_PORT *p)
+{
+// to write
+}
+
+/* Power off SIM == SIM_CMD_STOP 
+*  input  : none
+*  output : none
+*/
+
+void SIM_PowerOff(void)
+{
+    SIM_PORT *p;
+    volatile SYS_UWORD16 cmd;
+
+
+
+    // Initialize pointers 
+    p = &(Sim[0]);
+
+
+    // Reset and wait a while
+    cmd = p->c->cmd;
+    p->c->cmd = (cmd & MASK_CMD) | SIM_CMD_STOP;
+
+    ind_os_sleep(5);    //wait for falling of SIM signals (RESET/CLK/IO)
+
+    #if(ANLG_FAM == 1) 
+      //disable VCC : disable level shifter then SVDD
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCCTRL1) & MODE_DIS_SIMEN);
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCCTRL1) & MODE_DIS_SIMLDOEN);
+    #elif(ANLG_FAM == 2) 
+      //disable VCC : disable level shifter then SVDD
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCSIM) & MODE_DIS_SIMEN);
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCSIM) & MODE_DIS_SIMLDOEN);
+    #elif(ANLG_FAM == 3)
+      //disable VCC : disable level shifter then SVDD
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & MODE_DIS_SIMEN);
+      ABB_wa_VRPC (ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & MODE_DIS_SIMLDOEN);
+    #endif
+
+    ind_os_sleep(10);    //wait for falling of VCC commanf by ABB
+
+    p->c->cmd = 0x0000;   //disable clock of sim module
+
+    if ((SIM_sleep_status == SIM_SLEEP_DESACT) || (SIM_sleep_status == SIM_SLEEP_ACT))
+    {   //SIM sleep timer is not more needed
+        status_os_sim = NU_Delete_Timer (&SIM_timer);
+    }
+}
+
+
+/*
+ * SIM_Init
+ *
+ * Function for backward compatibility only
+ *
+ */
+
+void SIM_Init(void (Insert(SIM_CARD *cP)), void (Remove(void)))
+{
+    // Call SIM Registration function.
+    (void) SIM_Register (Insert, Remove);
+}
+
+/*
+ * SIM_Initialize
+ *
+ * Initialize data structures.
+ *
+ */
+
+void SIM_Initialize(void)
+{
+    int n;
+    SIM_PORT *p;
+    volatile SYS_UWORD32 dum;
+
+    /* FreeCalypso addition */
+    ffs_file_read("/etc/SIM_spenh", &SIM_allow_speed_enhancement, 1);
+
+    // Initialize registers 
+    p = &(Sim[0]);
+    p->c = (SIM_CONTROLLER *) SIM_CMD;
+
+    p->errorSIM = 0;
+    dum = (volatile SYS_UWORD32) SIM_Dummy;         // to force linking SIM32
+
+    status_os_sim = NU_Create_Timer (&SIM_timer, "SIM_sleep_timer", &SIM_SleepMode_In,
+                    0, SIM_SLEEP_WAITING_TIME, 0, NU_DISABLE_TIMER);
+    //timer start only with NU_Control_Timer function
+    //waiting time set to 2.3s
+    SIM_sleep_status = SIM_SLEEP_NONE;
+    
+#ifdef SIM_RETRY
+    SimRetries = 0;
+#endif
+}
+
+/*
+ * SIM_Register
+ *
+ * SIM Registration function: Initialize callback functions
+ *
+ * Insert(void) : pointer to the function called when a card is inserted
+ * Remove(void) : pointer to the function called when the card is removed
+ *
+ */
+
+SYS_UWORD16 SIM_Register(void (Insert(SIM_CARD *cP)), void (Remove(void)))
+{
+    SIM_PORT *p;
+
+    // Initialize pointers 
+    p = &(Sim[0]);
+
+    p->InsertFunc = Insert;
+    p->RemoveFunc = Remove;
+
+    return (SIM_OK);
+}
+
+
+/*
+ * High level routines : mapped to GSM 11.11 function calls
+ *
+ * Uses a Nucleus semaphore to ensure no simultaneous access to SIM and buffer
+ *    
+ * Each routine does :
+ *    write command
+ *    sleep long enough for the expected transmission and reception
+ *    return rest code
+ *
+ *    SYS_UWORD8 *result :  pointer to the string return by the SIM card
+ *    SYS_UWORD8 *rcvSize : size of the string return by the SIM card
+ *
+ *    other parameters : parameters needed by the SIM card to 
+ *                       execute the function.
+ *   
+ */
+//unsigned char SIM_flag = 0;
+
+
+/*
+ * SIM_Select
+ *
+ * Select a DF or a EF
+ */
+SYS_UWORD16 SIM_Select(SYS_UWORD16 id, SYS_UWORD8 *dat, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int res;
+	
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_SELECT; 
+    p->xbuf[2] = 0;
+    p->xbuf[3] = 0;
+    p->xbuf[4] = 2; 
+    p->xbuf[5] = id >> 8;       // high byte
+    p->xbuf[6] = id & 0xFF;     // low byte
+
+
+    res = SIM_Command(p, 2, dat, rcvSize);   
+    /* Change from to 10 to 15 for specific SIM card (Racal) */
+
+//	if (id == 0x6F07)
+//		SIM_flag = 1;
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AACMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 7);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AAANS", 5);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_Status
+ *    
+ *  Returns data received from card and number of bytes received
+ */
+SYS_UWORD16 SIM_Status(SYS_UWORD8 *dat, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+
+    short len = 0x16;            // length specified in GSM 11.11
+    int res;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_STATUS;
+    p->xbuf[2] = 0;
+    p->xbuf[3] = 0;
+    p->xbuf[4] = len; 
+
+    res = SIM_Command(p, 0, dat, rcvSize);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ABCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ABANS", 5);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+/*
+ * SIM_Status_Extended
+ *    
+ *  Returns data received from card and number of bytes received
+ *  Add extra parameter len : number of returned byte
+ */
+SYS_UWORD16 SIM_Status_Extended(SYS_UWORD8 *dat, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_STATUS;
+    p->xbuf[2] = 0;
+    p->xbuf[3] = 0;
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    res = SIM_Command(p, 0, dat, rcvSize);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ACCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ACANS", 5);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_ReadBinary
+ *
+ * Read data from the current EF
+ */
+SYS_UWORD16 SIM_ReadBinary(SYS_UWORD8 *dat, SYS_UWORD16 offset, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_READ_BINARY;
+    p->xbuf[2] = offset >> 8; 
+    p->xbuf[3] = offset & 0xFF; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    res = SIM_Command(p, 0, dat, rcvSize);
+
+//	if (SIM_flag) {
+//		SIM_flag = 0;
+//		dat[0] = 0x08;
+//	}
+		
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ADCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ADANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize>>8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(dat, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+
+}
+
+
+/*
+ * SIM_VerifyChv
+ *
+ * Verify the specified CHV (chvType)
+ */
+SYS_UWORD16 SIM_VerifyCHV(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD8 chvType, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    SYS_UWORD8 len;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+    len = 8;
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_VERIFY_CHV;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = chvType; 
+    p->xbuf[4] = len; 
+    for (i=0;i<8;i++)
+    {
+      p->xbuf[5+i] = *(dat+i);
+    }
+    res = SIM_Command(p, 8, result, rcvSize);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AECMD", 5);
+	SIM_dbg_write_trace(p->xbuf, len+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AEANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_RunGSMAlgo
+ *
+ * Authentication procedure
+ */
+SYS_UWORD16 SIM_RunGSMAlgo(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int len;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+
+    if(p->Freq_Algo)                                 //13/4 Mhz mandatory ??
+        p->c->conf1 = p->conf1 &= ~SIM_CONF1_SCLKDIV;
+
+    len = 16;
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_RUN_GSM_ALGO;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = len; 
+
+    for (i=0;i<len;i++)
+    {
+        p->xbuf[5+i] = *(dat+i);
+    }
+    res = SIM_Command(p, len, result, rcvSize);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AFCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, len+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AFANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    if(p->Freq_Algo)
+        p->c->conf1 = p->conf1 |= SIM_CONF1_SCLKDIV;
+
+
+    return(res);
+}
+
+
+/*
+ * SIM_GetResponse
+ *
+ * Get data from the card
+ *
+ * SYS_UWORD8 len : length of the data to get
+ */
+SYS_UWORD16 SIM_GetResponse(SYS_UWORD8 *dat, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_GET_RESPONSE;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    res = SIM_Command(p, 0, dat, rcvSize);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AGCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AGANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(dat, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_ChangeCHV
+ *
+ * Change the specified CHV (chvType)
+ */
+SYS_UWORD16 SIM_ChangeCHV(SYS_UWORD8 *result,SYS_UWORD8 *oldChv, SYS_UWORD8 *newChv, SYS_UWORD8 chvType,  SYS_UWORD16 *lP)
+{
+    SIM_PORT *p;
+    SYS_UWORD16 len;
+    int i;
+    SYS_UWORD16 res;
+
+    p = &(Sim[0]);
+    len = 16;
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_CHANGE_CHV;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = chvType; 
+    p->xbuf[4] = (SYS_UWORD8)len; 
+
+    // Copy bytes to buffer
+    for (i=0;i<8;i++)
+    {
+      p->xbuf[5+i] = *(oldChv+i);
+    }
+    for (i=0;i<8;i++)
+    {
+      p->xbuf[13+i] = *(newChv+i);
+    }
+    res = SIM_Command(p, len, result, lP);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AHCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, len+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AHANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*lP >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*lP);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *lP);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_DisableCHV
+ *
+ * Disable CHV 1
+ */
+SYS_UWORD16 SIM_DisableCHV(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 *lP)
+{
+    SIM_PORT *p;
+    int len;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+
+    len = 8;
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_DISABLE_CHV;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 1; 
+    p->xbuf[4] = 8; 
+    for (i=0;i<8;i++)
+    {
+      p->xbuf[5+i] = *(dat+i);
+    }
+    res = SIM_Command(p, len, result, lP);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AICMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 8+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AIANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*lP >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*lP);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *lP);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+
+}
+
+
+/*
+ * SIM_EnableCHV
+ *
+ * Enable CHV 1
+ */
+SYS_UWORD16 SIM_EnableCHV(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 *lP)
+{
+    SIM_PORT *p;
+    int len;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+
+    len = 8;
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_ENABLE_CHV;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 1; 
+    p->xbuf[4] = (SYS_UWORD8)len; 
+
+    for (i=0;i<len;i++)
+    {
+      p->xbuf[5+i] = *(dat+i);
+    }
+
+    res = SIM_Command(p, len, result, lP);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AJCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, len+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AJANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*lP >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*lP);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *lP);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+
+/*
+ * SIM_UnblockCHV
+ *
+ * Unblock the specified CHV (chvType) and store a new CHV
+ */
+SYS_UWORD16 SIM_UnblockCHV(SYS_UWORD8 *result, SYS_UWORD8 *unblockChv, SYS_UWORD8 *newChv,
+                      SYS_UWORD8 chvType, SYS_UWORD16 *lP) 
+{
+    SIM_PORT *p;
+    int len;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+    len = 16;
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_UNBLOCK_CHV;
+    p->xbuf[2] = 0;
+    p->xbuf[3] = chvType;
+    p->xbuf[4] = (SYS_UWORD8)len; 
+    for (i=0;i<8;i++)
+    {
+      p->xbuf[5+i] = *(unblockChv+i);
+    }
+    for (i=0;i<8;i++)
+    {
+      p->xbuf[13+i] = *(newChv+i);
+    }
+
+    res = SIM_Command(p, len, result, lP);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AKCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, len+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AKANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*lP >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*lP);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *lP);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+/*
+ * SIM_Invalidate
+ *
+ * Invalidate the current EF
+ */
+SYS_UWORD16 SIM_Invalidate(SYS_UWORD8 *rP, SYS_UWORD16 *lP)
+{
+    SIM_PORT *p;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_INVALIDATE;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = 0; 
+
+    res = SIM_Command(p, 0, rP, lP);
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ALCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ALANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*lP >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*lP);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(rP, *lP);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+/*
+ * SIM_Rehabilitate
+ *
+ * Rehabilitate the current EF
+ */
+SYS_UWORD16 SIM_Rehabilitate(SYS_UWORD8 *rP, SYS_UWORD16 *lP)
+{
+    SIM_PORT *p;
+    int len;
+    int res;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_REHABILITATE;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = 0;
+
+    res = SIM_Command(p, 0, rP, lP);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AMCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AMANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*lP >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*lP);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(rP, *lP);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+
+}
+
+
+/*
+ * SIM_UpdateBinary
+ *
+ * Store data in the current transparent EF
+ */
+SYS_UWORD16 SIM_UpdateBinary(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 offset, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int i;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_UPDATE_BINARY;
+    p->xbuf[2] = offset >> 8; 
+    p->xbuf[3] = offset & 0xFF; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    for (i=0;i<llen;i++)
+    {
+      p->xbuf[5+i] = *(dat+i);
+    }
+    res = SIM_Command(p, llen, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ANCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, llen+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ANANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+
+}
+
+
+/*
+ * SIM_ReadRecord
+ *
+ * Read a record (recNum) from the current linear fixed or cyclic EF
+ */
+SYS_UWORD16 SIM_ReadRecord(SYS_UWORD8 *dat, SYS_UWORD8 mode, SYS_UWORD8 recNum, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_READ_RECORD;
+    p->xbuf[2] = recNum; 
+    p->xbuf[3] = mode; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    res = SIM_Command(p, 0, dat, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AOCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, llen+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AOANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(dat, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+
+}
+
+#ifdef SIM_APDU_TEST
+SYS_UWORD8 snd[270];
+SYS_UWORD8 rec[270];
+SYS_UWORD8 logchan;
+SYS_UWORD16 recl;
+unsigned short resopen, resclose, rescmd;
+#endif
+
+#ifdef SIM_SAT_REFRESH_TEST
+SIM_CARD ptr;
+SYS_UWORD16 lrcvSize;
+SYS_UWORD8 ldat[20];
+#endif
+
+/*
+ * SIM_UpdateRecord
+ *
+ * Store a record (recNum) in the current linear fixed or cyclic EF
+ */
+SYS_UWORD16 SIM_UpdateRecord(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD8 mode, SYS_UWORD8 recNum, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int i;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+#ifdef SIM_SAT_REFRESH_TEST
+// do 1000 times the following sequence
+for (i=0;i<1000;i++) {
+SIM_PowerOff();
+SIM_Restart(&ptr);
+SIM_Select((SYS_UWORD16)0x7f10, ldat, &lrcvSize);
+SIM_Select((SYS_UWORD16)0x6f3a, ldat, &lrcvSize);
+}
+#endif
+#ifdef SIM_APDU_TEST
+	// send OPEN LOGICAL CHANNEL
+	snd[0] = 0x00;
+	snd[1] = 0x70;
+	snd[2] = 0x00;
+	snd[3] = 0x00;
+	snd[4] = 0x01;
+	resopen = SIM_XchTPDU(&snd[0], 5, &rec[0], 1, &recl);
+	if (resopen == 0x9000) {
+		logchan = rec[0];
+
+		// Select AID PKCS
+		snd[0] = logchan;
+		snd[1] = 0xA4;
+		snd[2] = 0x04;
+		snd[3] = 0x00;
+		snd[4] = 0x0C;
+		snd[5] = 0xA0;
+		snd[6] = 0x00;
+		snd[7] = 0x00;
+		snd[8] = 0x00;
+		snd[9] = 0x63;
+		snd[10] = 0x50;
+		snd[11]  = 0x4B;
+		snd[12] = 0x43;
+		snd[13] = 0x53;
+		snd[14] = 0x2D;
+		snd[15] = 0x31;
+		snd[16] = 0x35;
+		rescmd = SIM_XchTPDU(&snd[0], 17, &rec[0], 0, &recl);
+
+		// Select file EF odf
+		snd[0] = 0x80 | logchan;
+		snd[1] = 0xA4;
+		snd[2] = 0x00;
+		snd[3] = 0x00;
+		snd[4] = 0x02;
+		snd[5] = 0x50;
+		snd[6] = 0x31;
+		rescmd = SIM_XchTPDU(&snd[0], 7, &rec[0], 0, &recl);
+
+		// get response EF odf
+		snd[0] = logchan;
+		snd[1] = 0xC0;
+		snd[2] = 0x00;
+		snd[3] = 0x00;
+		snd[4] = rescmd;
+		rescmd = SIM_XchTPDU(&snd[0], 5, &rec[0], snd[4], &recl);
+
+		// read binary EF odf
+		snd[0] = 0x80 | logchan;
+		snd[1] = 0xB0;
+		snd[2] = 0x00;
+		snd[3] = 0x00;
+		snd[4] = rec[3]-16;
+		rescmd = SIM_XchTPDU(&snd[0], 5, &rec[0], snd[4], &recl);
+
+		// Select file EF cdf
+		snd[0] = 0x80 | logchan;
+		snd[1] = 0xA4;
+		snd[2] = 0x00;
+		snd[3] = 0x00;
+		snd[4] = 0x02;
+		snd[5] = 0x51;
+		snd[6] = 0x03;
+		rescmd = SIM_XchTPDU(&snd[0], 7, &rec[0], 0, &recl);
+
+		// get response EF odf
+		snd[0] = logchan;
+		snd[1] = 0xC0;
+		snd[2] = 0x00;
+		snd[3] = 0x00;
+		snd[4] = rescmd;
+		rescmd = SIM_XchTPDU(&snd[0], 5, &rec[0], snd[4], &recl);
+
+		// read binary EF cdf
+		snd[0] = 0x80 | logchan;
+		snd[1] = 0xB0;
+		snd[2] = 0x00;
+		snd[3] = 0x00;
+		snd[4] = 0xff;
+		rescmd = SIM_XchTPDU(&snd[0], 5, &rec[0], snd[4], &recl);
+
+		// read binary EF cdf
+		snd[0] = 0x80 | logchan;
+		snd[1] = 0xB0;
+		snd[2] = 0x00;
+		snd[3] = 0x00;
+		snd[4] = 0x00;
+		rescmd = SIM_XchTPDU(&snd[0], 5, &rec[0], 256, &recl);
+
+
+	}
+
+#endif
+
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_UPDATE_RECORD;
+    p->xbuf[2] = recNum; 
+    p->xbuf[3] = mode; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    for (i=0;i<llen;i++)
+    {
+        p->xbuf[5+i] = *(dat+i);
+    }
+
+    res = SIM_Command(p, llen, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"APCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, llen+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"APANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+
+#ifdef SIM_APDU_TEST
+
+	// send CLOSE LOGICAL CHANNEL
+	snd[0] = 0x00;
+	snd[1] = 0x70;
+	snd[2] = 0x80;
+	snd[3] = logchan;
+	snd[4] = 0x00;
+	resclose = SIM_XchTPDU(&snd[0], 5, &rec[0], 0, &recl);
+
+#endif
+
+    return(res);
+}
+
+/*
+ * SIM_Seek
+ *
+ * Search data in a linear fixed or cyclic EF.
+ * return the first record number in which it found the data.
+ */
+SYS_UWORD16 SIM_Seek(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD8 mode, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+   SIM_PORT *p;
+   int i;
+   int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+   p = &(Sim[0]);
+
+   p->xbuf[0] = GSM_CLASS;
+   p->xbuf[1] = SIM_SEEK;
+   p->xbuf[2] = 0; 
+   p->xbuf[3] = mode; 
+   p->xbuf[4] = (SYS_UWORD8)llen; 
+
+   for (i=0;i<llen;i++)
+   {
+      p->xbuf[5+i] = *(dat+i);
+   }
+
+   res = SIM_Command(p, llen, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AQCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, llen+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AQANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+   return(res);
+}
+
+/*
+ * SIM_Increase
+ *
+ * Add value to a record of a cyclic EF
+ */
+SYS_UWORD16 SIM_Increase(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int len;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+
+    len = 3;
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_INCREASE;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = 3; 
+
+    for (i=0;i<3;i++)
+    {
+        p->xbuf[5+i] = *(dat+i);
+    }
+
+    res = SIM_Command(p, len, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ARCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 3+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ARANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+/*
+ * SIM_TerminalProfile
+ *
+ * Used by ME to send its toolkit capabilities to SIM
+ */
+SYS_UWORD16 SIM_TerminalProfile(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int i;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_TERMINAL_PROFILE;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    for (i=0;i<llen;i++)
+    {
+        p->xbuf[5+i] = *(dat+i);
+    }
+
+    res = SIM_Command(p, llen, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ASCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, llen+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ASANS", 5);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_FETCH
+ *
+ * Used by ME to inquiry of what SIM toolkit need to do
+ */
+SYS_UWORD16 SIM_Fetch(SYS_UWORD8 *result, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int i;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_FETCH;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+
+    res = SIM_Command(p, 0, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ATCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, 5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"ATANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_TerminalResponse *
+ * Used for ME to respond at a SIM toolkit command
+ */
+SYS_UWORD16 SIM_TerminalResponse(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int i;
+    int res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_TERMINAL_RESPONSE;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    for (i=0;i<llen;i++)
+    {
+        p->xbuf[5+i] = *(dat+i);
+    }
+
+    res = SIM_Command(p, llen, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AUCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, llen+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AUANS", 5);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+/*
+ * SIM_Envelope
+ *
+ * Used by Network to tansfert data download to the SIM in a transparent way for user
+ */
+SYS_UWORD16 SIM_Envelope(SYS_UWORD8 *result, SYS_UWORD8 *dat, SYS_UWORD16 len, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT    *p;
+    int         i;
+    int         res;
+	SYS_UWORD16 llen = len & SIM_UWORD16_MASK;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = GSM_CLASS;
+    p->xbuf[1] = SIM_ENVELOPE;
+    p->xbuf[2] = 0; 
+    p->xbuf[3] = 0; 
+    p->xbuf[4] = (SYS_UWORD8)llen; 
+
+    for (i=0;i<llen;i++)
+    {
+        p->xbuf[5+i] = *(dat+i);
+    }
+
+    res = SIM_Command(p, llen, result, rcvSize);        
+
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AVCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, llen+5);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AVANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+
+
+
+
+
+
+
+/*
+ * SIM_XchTPDU *
+ * Used for ME to send generic command to WIM Card
+ */
+SYS_UWORD16 SIM_XchTPDU(SYS_UWORD8 *dat, SYS_UWORD16 trxLen, SYS_UWORD8 *result,
+						SYS_UWORD16 rcvLen, SYS_UWORD16 *rcvSize)
+{
+    SIM_PORT *p;
+    int i;
+    int res;
+
+    p = &(Sim[0]);
+
+    p->xbuf[0] = dat[0];
+    p->xbuf[1] = dat[1];
+    p->xbuf[2] = dat[2]; 
+    p->xbuf[3] = dat[3]; 
+    p->xbuf[4] = dat[4]; 
+
+    for (i=5;i<trxLen;i++)
+    {
+        p->xbuf[i] = dat[i];
+    }
+
+	// enable the WIM behavior of the sim driver
+   	p->apdu_ans_length = rcvLen;
+
+    res = SIM_Command(p, (trxLen - 5), result, rcvSize);        
+
+	// disable the WIM behavior of the sim driver
+   	p->apdu_ans_length = 0;
+	
+#ifdef SIM_DEBUG_TRACE
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AWCMD", 5);
+	SIM_dbg_write_trace(p->xbuf, trxLen);
+	SIM_dbg_write_trace((SYS_UWORD8 *)"AWANS", 5);
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(*rcvSize >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(*rcvSize);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(result, *rcvSize);
+	SIM_dbg_tmp[0] = (SYS_WORD8)(res>>8);
+	SIM_dbg_tmp[1] = (SYS_WORD8)res;
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+	SIM_dbg_write_trace(SIM_dbg_null, SIM_DBG_NULL);
+	if (SIM_dbg_tdma_diff > SIM_dbg_max_interchardelay)
+	   SIM_dbg_max_interchardelay = SIM_dbg_tdma_diff;
+	SIM_dbg_tmp[0] = (SYS_UWORD8)(SIM_dbg_tdma_diff >> 8);
+	SIM_dbg_tmp[1] = (SYS_UWORD8)(SIM_dbg_tdma_diff);
+	SIM_dbg_write_trace(SIM_dbg_tmp, 2);
+#endif
+
+    return(res);
+}
+
+
+
+
+
+
+
+
+/*
+* Use to detect end of characters reception
+* input:    p       pointer on sim structure
+*           n       number of extra character to send
+*
+* output:   return 0 if sucess
+*                  SIM_ERR_x in case of error
+*
+*/
+
+SYS_UWORD16 SIM_WaitReception(SIM_PORT *p)
+{
+    SYS_UWORD16 returncode;
+
+
+    //analyse the nature of the command to execute
+
+    if (
+    	(p->xbuf[1] == 0x12) || 
+    	(p->xbuf[1] == 0xB2) || 
+    	(p->xbuf[1] == 0xB0) || 
+    	(p->xbuf[1] == 0xF2) || 
+    	(p->xbuf[1] == 0xC0) || 
+    	(p->apdu_ans_length != 0)
+       )       
+    //FETCH, READ_RECORD, READ_BINARY, STATUS, GET_RESPONSE commands == receive command
+    {
+        if (p->xbuf[4] == 0)                    //if P3 == 0 when sending receive command
+        {
+            p->expected_data = 256; 
+        }
+        else
+        {
+            p->expected_data = p->xbuf[4];
+        }
+
+        p->moderx = 1;                          //wait for procedure byte
+
+        if (returncode = SIM_Waitforchars (p, p->etu9600))
+        {
+            return returncode;
+        }
+    }
+    else    //direct command : INVALIDATE, REHABILITATE, SLEEP
+    {
+        p->moderx = 5;      //mode reception of SW1/SW2
+
+        if (returncode = SIM_Waitforchars (p, p->etu9600))
+        {
+            return returncode;
+        }
+    }
+    return (0);
+}
+
+
+
+/*
+* Use to read file characteristics information
+* input:    p       pointer on sim structure
+*
+* output:   return 0 if sucess
+*                  1 in case of error
+*
+*/
+
+
+SYS_UWORD8 SIM_GetFileCharacteristics(SIM_PORT *p)
+{
+    int   res;
+    SYS_UWORD8  ubuf[40];
+    SYS_UWORD16  sz;
+
+    res = SIM_Select(DF_GSM, ubuf, &sz);
+    if ((res & 0xFF00) != 0x9F00)
+    {
+        res = SIM_Select(DF_DCS1800, ubuf, &sz);                                        
+        if ((res & 0xFF00) != 0x9F00)                                
+        {
+            return (1);
+        }
+    }
+    res = SIM_GetResponse( ubuf, res & 0x00FF , &sz);
+    if (res != 0x9000)
+        return (1);
+
+    p->FileC = ubuf[13];
+    return (0);
+}  
+  
+/*
+* Use to determine value of b2 in file caracteristics contained in response
+* of SELECT Master File command
+* return    0 if no preferred speed during authentication
+*           1 if 13/4Mhz mandatory 
+*
+*
+*/
+ 
+void SIM_Interpret_FileCharacteristics(SIM_PORT *p)
+{
+    //interpret b2 bit for operating authentication speed
+    if((p->conf1 & 0x0020) && (p->FileC & 0x02))  
+    {
+        p->Freq_Algo = 1;                                 
+    }
+
+    //interpret Clock stop behavior
+	// modified by J. Yp-Tcha to integrate all the behaviors required by ETSI.
+	// 18/11/2002 : TI Chip always allowed low level, high level is hard dependant
+
+	if ((p->FileC & SIM_CLK_STOP_MASK) == SIM_CLK_STOP_NOT_ALLWD) {
+		/* Sim Clock Stop Not Allowed */
+		SIM_sleep_status = SIM_SLEEP_NOT_ALLOWED;
+		/* There is not need to modifiy p->conf1 */ 
+        status_os_sim = NU_Delete_Timer (&SIM_timer);
+	}
+	else {
+		if ((p->FileC & SIM_CLK_STOP_MASK) == SIM_CLK_STOP_ALLWD) {
+			/* Sim Clock Stop Allowed, no prefered level */
+			/* Default value for TI Chip shall always be Low Level */
+	        SIM_sleep_status = SIM_SLEEP_DESACT;
+		    p->c->conf1 = p->conf1 &= ~SIM_CONF1_SCLKLEV;
+		}
+		else {
+			/* Clock Stop is allowed, the level shall be checked */
+			if ((p->FileC & SIM_CLK_STOP_HIGH) == SIM_CLK_STOP_HIGH) {
+				/* high level is mandatory */
+/* OMEGA/NAUSICA can not handle sim stop clock at high level */
+#ifndef ANALOG1
+	            SIM_sleep_status = SIM_SLEEP_DESACT;
+    	        p->c->conf1 = p->conf1 |= SIM_CONF1_SCLKLEV;
+#else
+				/* Sim Clock Stop Not Allowed because the interface do not support this level */
+				SIM_sleep_status = SIM_SLEEP_NOT_ALLOWED;
+				/* There is not need to modifiy p->conf1 */ 
+		        status_os_sim = NU_Delete_Timer (&SIM_timer);
+#endif
+			}
+			else {
+				/* by default, Low Level is allowed */
+	            SIM_sleep_status = SIM_SLEEP_DESACT;
+	            p->c->conf1 = p->conf1 &= ~SIM_CONF1_SCLKLEV;
+			}
+		}
+	}
+    if (SIM_sleep_status == SIM_SLEEP_NONE)
+    {
+        status_os_sim = NU_Delete_Timer (&SIM_timer);
+    }
+}
+
+/*
+* Use to evaluate need of sending PTS procedure regarding
+* the ATR. If default not used, PTS initiates F and D adequate values
+* for speed enhancement.
+* In case of 2 wrong PTS answer (speed enhanced), a third PTS with default value
+* is used. If the third PTS attempt failed, the ME reset the SIM and use default
+* value.
+*  Return Value : SIM_ERR_READ, SIM_ERRCARDREJECT, SIM_ERR_WAIT
+ *
+*/
+
+
+SYS_UWORD16 SIM_PTSprocedure(SIM_CARD *cP, SIM_PORT *p)
+{
+
+    SYS_UWORD8            TA1;
+    SYS_UWORD8            n;
+    SYS_UWORD8            err;
+
+    p->xbuf[0]       = 0xFF;                        //character of PTS proc to send
+    p->xbuf[1]       = 0; 
+    p->xbuf[2]       = 0xFF;
+    p->xbuf[3]       = 0x7B;
+
+      //TA1,TB1,TC1,TD1 present in ATR ?
+
+    n   = 3;
+
+    p->PTS_Try++;
+
+    if (p->PTS_Try > 4)
+    {
+        return (SIM_ERR_CARDREJECT);  
+    }                       // at the fourth attempt, PTS procedure is unusefull. Use default value.
+                            //TA1 present?  Test 27.11.2.6
+    else if ( p->PTS_Try == 4)
+    {
+        SIM_Calcetu (p);
+        return (0);    
+    }
+    
+    if(cP->AtrData[1] & 0x10)
+    {
+        TA1 = cP->AtrData[2];
+    }
+    else                    //if TA1 not present, return
+    {
+        SIM_Calcetu (p);
+        return (0);
+    }
+
+    if (TA1 >= 0x94 && SIM_allow_speed_enhancement)
+    {
+// JYT 26/9/2003 to check correct behavior of the SIM Driver vs the PPS.
+//#ifdef NOTTOLOADBECAUSENOTTESTED
+//	SIM_Calcetu (p);
+//        return (0);         //temporary disabling of speed enhancement feature
+
+        if (p->PTS_Try <= 2)
+        {
+            n = 4;
+            p->xbuf[1] = 0x10;
+            p->xbuf[2] = 0x94; // if speed enhancement, then at least (and at most) F = 512 and D = 8 is supported
+        }
+//#endif
+    }
+
+    if ((TA1 == 0x11) || (TA1 == 0x01))
+    {
+        SIM_Calcetu (p);
+        return (0);
+    }                       //if TA1 != 0x11 and 0x94, need to send PTS request
+                            //transmit request of speed enhancement : PTS
+    SIM_WriteBuffer(p, 0, n);    
+
+    p->moderx = 0;          //mode of normal reception
+    p->expected_data = n;
+
+    if (err = SIM_Waitforchars (p, p->etu9600))
+    {
+      return (err);
+    }
+                            //should received same chars as PTS request
+    if ((p->rbuf[0] != p->xbuf[0]) || (p->rbuf[1] != p->xbuf[1]) || 
+    (p->rbuf[2] != p->xbuf[2])) 
+    {
+      return(SIM_ERR_READ);
+    }
+
+
+    if (n == 4)
+    {
+        if (p->rbuf[3] != p->xbuf[3])
+        {
+            return(SIM_ERR_READ);
+        }   
+        
+        //correct response from SIM : with speed enhanced
+        p->c->conf1 = p->conf1 |= SIM_CONF1_ETU; //set F=512 D=8
+    }
+
+    SIM_Calcetu (p);
+    return (0);
+
+}
+
+/*
+* procedure of WARM reset consists on asserting
+* reset signal at 0 during at least 400 ETU
+* input     p pointer of type SIM_PORT
+*/
+
+void SIM_WARMReset (SIM_PORT *p)
+{
+
+    p->c->conf1 = p->conf1 &= ~SIM_CONF1_SRSTLEV;
+    ind_os_sleep (p->etu400);  /// wait 400 ETU
+    p->c->conf1 = p->conf1 |= SIM_CONF1_SRSTLEV;
+    p->rx_index = 0;
+
+}
+
+
+/*
+* procedure use to get out sleepMode
+* input     p pointer of type SIM_PORT
+*/
+
+void SIM_SleepMode_In (SYS_UWORD32 param)
+{
+    if (SIM_sleep_status == SIM_SLEEP_DESACT)
+    {
+        (&(Sim[0]))->c->conf1 &= ~SIM_CONF1_SCLKEN;  //disabled the clock for the SIM card
+        SIM_sleep_status = SIM_SLEEP_ACT;
+    }
+    status_os_sim = NU_Control_Timer (&SIM_timer,  NU_DISABLE_TIMER);
+}
+
+
+
+
+/*
+* procedure use to get out sleepMode
+* input     p pointer of type SIM_PORT
+*/
+
+void SIM_SleepMode_Out (SIM_PORT *p)
+{
+    if (SIM_sleep_status == SIM_SLEEP_ACT)
+    {
+        p->c->conf1 = p->conf1 |= SIM_CONF1_SCLKEN;
+        // WCS patch for NU_Sleep(0) bug
+        if (p->startclock > 0)
+		ind_os_sleep (p->startclock);    
+        // End WCS patch
+        SIM_sleep_status = SIM_SLEEP_DESACT;
+    }    
+}
+               
+/*
+*  procedure to parse ATR dynamically
+*  input     p pointer of type SIM_PORT
+*  output    return error code
+*  SIM_ERR_WAIT, p->errorSIM
+*  SIM_ERR_CARDREJECT,
+*
+*
+*/
+
+
+SYS_UWORD16 SIM_ATRdynamictreatement (SIM_PORT *p, SIM_CARD *cP)
+{
+
+    volatile SYS_UWORD8   HistChar;
+    volatile SYS_UWORD8   InterfChar;
+    SYS_UWORD16          countT;
+    SYS_UWORD16          mask;
+    SYS_UWORD16          returncode;
+    SYS_UWORD8            i;
+    SYS_UWORD8            firstprotocol;    
+    SYS_UWORD8            Tx,T;
+    SYS_UWORD8            TDi;
+    SYS_UWORD8            position_of_TC1, position_of_TB1;
+    SYS_UWORD8            another_protocol_present;
+    SYS_UWORD16            wait80000clk;
+        
+    i               = 0;
+    //wait for TS and T0
+    p->moderx       = 0;
+    p->expected_data= 1;
+    firstprotocol   = 0;
+    position_of_TC1 = 0;
+    position_of_TB1 = 0;
+    another_protocol_present = 0;
+    wait80000clk    = 6; // > 24 ms
+
+    //wait for first character TS of ATR sequence. It should arrive before 80000sclk
+    if (returncode = SIM_Waitforchars (p, wait80000clk))
+    {
+        return returncode;
+    }
+    
+    //wait for T0
+    p->expected_data++; 
+    if (returncode = SIM_Waitforchars (p, p->etu9600))
+    {
+        return returncode;
+    }
+
+	ind_os_sleep(220);
+
+    if (((p->rbuf[0] & 0xF0) == 0x30) && (p->rx_index != 0))
+    {
+        cP->Inverse = 0;
+    }
+        /*-----------------------------------------------------------*/
+        /*              Inverse convention card                      */
+            // If first byte is correct for inverse card, return success 
+    else if (((p->rbuf[0] & 0x0F) == 0x03) && (p->rx_index != 0))
+    {
+        cP->Inverse = 1;
+    }
+    else
+    {
+        return (SIM_ERR_CARDREJECT);  //Test 27.11.2.4.5
+    }
+
+    countT          = 0;
+    mask            = 0x10;
+    InterfChar      = 2;
+    TDi             = 1;
+
+
+    Tx = SIM_Translate_atr_char (p->rbuf[1], cP);
+
+    HistChar        = Tx & 0x0F;        //get K, number of transmitted historical character
+
+    
+    while (TDi != 0)
+    {
+        while (mask < 0x100)            //monitors interface chars
+        {
+            if ((Tx & mask) == mask)    //monitors if interface character TAx,TBx,TCx,TDc present
+            {
+                InterfChar++;
+            }
+                                        //wait for TC1 and save its position
+            if ((firstprotocol == 0) && ((Tx & 0x40) == mask))
+            {
+                position_of_TC1 = InterfChar - 1;            
+            }
+			if ((firstprotocol == 0) && ((Tx & 0x20) == mask))
+            {
+                position_of_TB1 = InterfChar - 1;            
+            }
+
+            mask = mask << 1;
+        }
+
+        p->expected_data = InterfChar;     //wait for TAi,TBi,TCi,TDi if present
+        
+        if (returncode = SIM_Waitforchars (p, p->etu9600))
+        {
+            return returncode;
+        }
+
+                                        //need to monitor if TC1 present and if equal to 0 or 255 on first protocol
+        if ((firstprotocol == 0) && (position_of_TC1 != 0))
+        {
+            T = SIM_Translate_atr_char (p->rbuf[position_of_TC1], cP);
+
+            if ((T != 0) && (T != 255)) //test 27.11.1.3
+            {                           //return Error in case of bad TC1 value            
+                return (SIM_ERR_CARDREJECT);            
+            }
+        }
+                                        //need to monitor if TB1 present and if differente from 0 on first protocol
+        if ((firstprotocol == 0) && (position_of_TB1 != 0))
+        {
+            T = SIM_Translate_atr_char (p->rbuf[position_of_TB1], cP);
+
+            if (T != 0) //ITU 
+            {                           //return Error in case of bad TB1 value            
+                return (SIM_ERR_CARDREJECT);            
+            }
+        }
+
+        if ((Tx & 0x80) == 0x80)        //TDi byte on first protocol must be 0
+        {                               //get new TD char
+            Tx = SIM_Translate_atr_char (p->rbuf[InterfChar - 1], cP);
+          
+            if ((Tx & 0x0F) != 0)
+            {
+                if (firstprotocol == 0) //if first protocol received is not T=0, card is rejected   
+                {
+                    return (SIM_ERR_CARDREJECT);            //protocol other than T=0
+                }    
+                else
+                {                       //if an another protocol T != 0 present, need to wait for TCK char
+                    another_protocol_present = 1;                
+                }
+            }
+            mask = 0x10;    
+            firstprotocol++;            //indicate another protocol T
+        }
+        else
+        {
+            TDi = 0;
+        }
+    }
+                                        //add TCK if necessary
+    p->expected_data =  HistChar + InterfChar + another_protocol_present;
+ 
+    if (returncode = SIM_Waitforchars (p, p->etu9600))
+    {
+        return returncode;
+    }
+
+    cP->AtrSize = p->rx_index;
+
+    if (cP->Inverse)        //inverse card
+    {
+        // Copy ATR data       
+        for (i=0;i<cP->AtrSize;i++)
+        {
+            cP->AtrData[i] = SIM_ByteReverse(p->rbuf[i]);    
+        }
+        p->c->conf1 = p->conf1 |= SIM_CONF1_CONV | SIM_CONF1_CHKPAR;
+    }
+    else                    //direct card
+    {
+        p->c->conf1 = p->conf1 |= SIM_CONF1_CHKPAR; //0x0409
+        // Copy ATR data       
+        for (i=0;i<cP->AtrSize;i++)
+        {
+            cP->AtrData[i] = p->rbuf[i];
+        }
+    }
+
+    return (0);
+}
+
+/*
+ ** SIM_Translate_atr_char 
+ *
+ *  FILENAME: sim.c
+ *
+ *  PARAMETERS: input   char to translate
+ *              cP      sim structure (indicates if inverse card present)
+ *  DESCRIPTION: return the correct value of input for inverse card
+ *
+ *  RETURNS: character after parsing
+ *           stays the same if direct card
+ */
+
+SYS_UWORD8 SIM_Translate_atr_char (SYS_UWORD8 input, SIM_CARD *cP)
+{
+    SYS_UWORD8 translated;
+
+    if (cP->Inverse)
+    {
+        translated = SIM_ByteReverse(input);    
+    }
+    else
+    {
+        translated = input;           //get character next char T0
+    }
+    return (translated);
+}
+
+
+
+/*
+* SIM_Waitforchars is used for waiting nbchar characters from SIM
+* input p          sim port
+*       max_wait   max number of TDMA to wait between 2 characters
+* output
+*       error code 0 if OK      
+*/
+
+
+SYS_UWORD16 SIM_Waitforchars (SIM_PORT *p, SYS_UWORD16 max_wait)
+{
+    volatile SYS_UWORD8    old_nb_char;
+    volatile SYS_UWORD16  countT;
+
+    if (p->moderx == 6)                 //use for reception of ACK when command need to transmit rest of data
+    {
+        p->ack = 0;
+        countT = 0;
+
+        while((p->ack == 0) && (p->moderx == 6)) 
+        {                               //if p->moderx change from 6 to 5, need to wait for SW1 and SW2
+
+            ind_os_sleep(1);
+            countT++;                   //implementation of software Waiting time overflow
+
+            if (p->null_received)       //if NULL char received, wait for next procedure char
+            {
+                countT = 0;
+                p->null_received = 0;
+            }
+
+            if (countT > max_wait)
+            {
+                return (SIM_ERR_WAIT);
+            }
+            if (p->errorSIM)
+            {
+                return(p->errorSIM);
+            }
+        }
+        if (p->moderx == 6)             //if transition to moderx = 5 in synchronous part
+        {                               //need to quit for SW1/SW2 reception
+            return (0);
+        }    
+    }
+    
+    if ((p->moderx != 6) && (p->moderx != 5))   //treatement of mode 0, 1, 2, 3, 4
+    {        
+        countT = 0;
+        old_nb_char = p->rx_index;
+											   //leave while if moderx == 5
+        while((p->rx_index < p->expected_data) && (p->moderx != 5)) 
+        {
+            ind_os_sleep(1);
+            countT++;                   //implementation of software Waiting time overflow
+
+            if (p->null_received)       //if NULL char received, wait for next procedure char
+            {
+                countT = 0;
+                p->null_received = 0;
+            }
+
+            if (countT > max_wait)
+            {
+                return (SIM_ERR_WAIT);
+            }
+            if (p->errorSIM)
+            {
+                return(p->errorSIM);
+            }
+            if (p->rx_index > old_nb_char)
+            {
+                old_nb_char = p->rx_index;  //if char received before max_wait TDMA, reset the counter
+                countT = 0;
+            }
+        } //end while
+		if (p->moderx == 0)
+		{
+			return (0);
+		}
+    }
+
+    if (p->moderx == 5)                 //use for reception of SW1 SW2
+    {
+        countT = 0;
+        old_nb_char = p->SWcount;
+
+        while(p->SWcount < 2) 
+        {                               //if p->moderx change from 6 to 5, need to wait for SW1 and SW2
+
+            ind_os_sleep(1);
+            countT++;                   //implementation of software Waiting time overflow
+
+            if (p->null_received)       //if NULL char received, wait for next procedure char
+            {
+                countT = 0;
+                p->null_received = 0;
+            }
+
+            if (countT > max_wait)
+            {
+                return (SIM_ERR_WAIT);
+            }
+            if (p->errorSIM)
+            {
+                return(p->errorSIM);
+            }
+            if (p->SWcount > old_nb_char)
+            {
+                old_nb_char = p->SWcount;  //if char received before max_wait TDMA, reset the counter
+                countT = 0;
+            }
+        }
+        p->SWcount = 0;                 //reset SWcount buffer index when SW1 SW2 received
+        return (0);
+	}
+	else		//treatement of abnormal case of the asynchronous state machine
+	{
+		return (SIM_ERR_ABNORMAL_CASE1);
+	}
+	
+}
+
+
+
+/*
+* SIM_Calcetu is used for calculating 9600 etu and 400 etu depending on sim clock freq
+*             and etu period
+* input p     sim port
+*/
+
+void SIM_Calcetu (SIM_PORT *p)
+{
+    if (p->conf1 & SIM_CONF1_SCLKDIV)   //clock input is 13/8 Mhz
+    {
+        if (p->conf1 & SIM_CONF1_ETU)   //etu period is 512/8*Tsclk
+        {
+            p->etu9600     = 319;    // old = 88, increase of 363%
+            p->etu400      = 6;
+            p->stopclock   = 18;
+            p->startclock = 8;
+        }
+        else                            //etu period is 372/1*Tsclk
+        {
+            p->etu9600     = 1815;   // old = 500, increase of 363%
+            p->etu400      = 28;
+            p->stopclock   = 94;
+            p->startclock = 38; 
+        }
+    }
+    else                                //clock input is 13/4 Mhz
+    {
+        if (p->conf1 & SIM_CONF1_ETU)   //etu period is 512/8*Tsclk
+        {
+            p->etu9600     = 159;   // old = 44, increase of 363%
+            p->etu400      = 3;
+            p->stopclock   = 9;
+            p->startclock = 4; 
+        }
+        else                            //etu period is 372/1*Tsclk
+        {
+            p->etu9600     = 907;  // old = 250, increase of 363%
+            p->etu400      = 14;
+            p->stopclock   = 47;
+            p->startclock = 19; 
+        }
+    }  
+}
+
+
+
+
+
+/*
+ * Set the level shifter voltage for start up sequence
+ *
+ */
+
+SYS_UWORD8 SIM_StartVolt (SYS_UWORD8 ResetFlag) 
+{
+	SYS_UWORD8 abbmask;
+
+#if(ANLG_FAM == 1)
+// we assume that in SIM_TYPE_5V there is nothing to do because it is the reset value
+  #if ((SIM_TYPE == SIM_TYPE_3V) || (SIM_TYPE == SIM_TYPE_3_5V))    // { shut down VCC from ABB and prepare to start at 3V mode
+	if (ResetFlag) {
+		abbmask = MODE_INIT_OMEGA_3V;
+    CurrentVolt   = SIM_3V;  // we assume the sim is 3v tech. from beginning.
+	}
+	else {
+		if (CurrentVolt == SIM_3V)
+			abbmask = MODE_INIT_OMEGA_3V;
+		else
+			abbmask = MODE5V_OMEGA;
+	}
+    ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCCTRL1) & 0xC0) | abbmask);
+    ind_os_sleep(1);         //wait for charge pump regulation
+    return(SIM_OK);
+  #endif
+#endif
+
+#if(ANLG_FAM == 2)
+    SYS_UWORD8 count = 0;
+// code for Iota
+// reset value for IOTA is for 1.8V, but specific procedure is needed
+  #if ((SIM_TYPE == SIM_TYPE_1_8V) || (SIM_TYPE == SIM_TYPE_1_8_3V))    // shut down VCC from ABB and prepare to start at 1.8V mode
+	if (ResetFlag) {
+		abbmask = MODE_INIT_IOTA_1_8V;
+        CurrentVolt   = SIM_1_8V;  // we assume the sim is 1.8v tech. from beginning.
+	}
+	else {
+		if (CurrentVolt == SIM_1_8V)
+			abbmask = MODE_INIT_IOTA_1_8V;
+		else
+			abbmask = MODE_INIT_IOTA_3V;
+	}
+    ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCSIM) & 0xF4) | abbmask);
+    while(count++ < 5)
+    {
+		if (ABB_Read_Register_on_page(PAGE1,VRPCSIM) & 0x04) // test RSIMRSU
+            return(SIM_OK);
+        ind_os_sleep(1);	
+    }
+    // IOTA failure activation
+    return(SIM_ERR_HARDWARE_FAIL);
+  #endif
+  // 3V only
+  #if (SIM_TYPE == SIM_TYPE_3V)
+	abbmask = MODE_INIT_IOTA_3V;
+	CurrentVolt   = SIM_3V;  // we assume the sim is 3v tech. from beginning.
+    ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCSIM) & 0xF4) | abbmask);
+    while(count++ < 5)
+    {
+		if (ABB_Read_Register_on_page(PAGE1,VRPCSIM) & 0x04) // test RSIMRSU
+            return(SIM_OK);
+        ind_os_sleep(1);	
+    }
+    // IOTA failure activation
+    return(SIM_ERR_HARDWARE_FAIL);
+  #endif
+#endif
+
+#if(ANLG_FAM == 3)
+  SYS_UWORD8 count = 0;
+// code for Syren
+// reset value for SYREN is for 1.8V, but specific procedure is needed
+  #if ((SIM_TYPE == SIM_TYPE_1_8V) || (SIM_TYPE == SIM_TYPE_1_8_3V))    // { shut down VCC from ABB and prepare to start at 1.8V mode
+	if (ResetFlag) {
+		abbmask = MODE_INIT_SYREN_1_8V;
+        CurrentVolt   = SIM_1_8V;  // we assume the sim is 1.8v tech. from beginning.
+	}
+	else {
+		if (CurrentVolt == SIM_1_8V)
+			abbmask = MODE_INIT_SYREN_1_8V;
+		else
+			abbmask = MODE_INIT_SYREN_3V;
+	}
+	ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & 0x1F4) | abbmask);
+    while(count++ < 5)
+    {
+		if (ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & 0x04) // test RSIMRSU
+            return(SIM_OK);
+        ind_os_sleep(1);
+    }
+    // SYREN failure activation
+    return(SIM_ERR_HARDWARE_FAIL);
+  #endif
+
+  // 3V only
+  #if (SIM_TYPE == SIM_TYPE_3V)
+	abbmask = MODE_INIT_SYREN_3V;
+	CurrentVolt   = SIM_3V;  // we assume the sim is 3v tech. from beginning.
+    ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & 0x1F4) | abbmask);
+    while(count++ < 5)
+    {
+      if (ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & 0x04) // test RSIMRSU
+            return(SIM_OK);
+      ind_os_sleep(1);
+    }
+    // SYREN failure activation
+    return(SIM_ERR_HARDWARE_FAIL);
+  #endif
+#endif
+}
+
+
+/*
+ * Set the level shifter to switch from 3V to 5V
+ *
+ */
+
+
+SYS_UWORD8 SIM_SwitchVolt (SYS_UWORD8 ResetFlag)
+{
+    SYS_UWORD8 count = 0;
+   	SYS_UWORD8 abbmask;
+        
+    SIM_PowerOff();
+
+    #if(ANLG_FAM == 1)
+      #if (SIM_TYPE == SIM_TYPE_3_5V)    // shut down VCC from ABB and prepare to start at 5V mode
+	if (ResetFlag) {
+		abbmask = MODE5V_OMEGA;
+        CurrentVolt   = SIM_5V;  
+	}
+	else {
+		if (CurrentVolt == SIM_3V)
+			abbmask = MODE_INIT_OMEGA_3V;
+		else
+			abbmask = MODE5V_OMEGA;
+	}
+	ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCCTRL1) & 0xC0) | abbmask);
+        return(SIM_OK);
+      #endif
+    #elif(ANLG_FAM == 2)
+      #if (SIM_TYPE == SIM_TYPE_1_8_3V)  // shut down VCC from ABB and prepare to start at 3V mode
+	if (ResetFlag) {
+		abbmask = MODE_INIT_IOTA_3V;
+        CurrentVolt   = SIM_3V; 
+	}
+	else {
+		if (CurrentVolt == SIM_1_8V)
+			abbmask = MODE_INIT_IOTA_1_8V;
+		else
+			abbmask = MODE_INIT_IOTA_3V;
+	}
+	ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCSIM) & 0xF4) | abbmask);
+       while(count++ < 5)
+       {
+          if (ABB_Read_Register_on_page(PAGE1,VRPCSIM) & 0x04)
+               return(SIM_OK);
+           ind_os_sleep(1);	
+       }
+       // IOTA failure activation
+       return(SIM_ERR_HARDWARE_FAIL);
+      #endif
+ #elif(ANLG_FAM == 3)
+      #if (SIM_TYPE == SIM_TYPE_1_8_3V)  // shut down VCC from ABB and prepare to start at 3V mode
+	if (ResetFlag) {
+		abbmask = MODE_INIT_SYREN_3V;
+        CurrentVolt   = SIM_3V; 
+	}
+	else {
+		if (CurrentVolt == SIM_1_8V)
+			abbmask = MODE_INIT_SYREN_1_8V;
+		else
+			abbmask = MODE_INIT_SYREN_3V;
+	}
+	ABB_wa_VRPC ((ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & 0x1F4) | abbmask);
+        while(count++ < 5)
+        {
+          if (ABB_Read_Register_on_page(PAGE1,VRPCSIMR) & 0x04)
+            return(SIM_OK);
+          ind_os_sleep(1);
+        }
+       // SYREN failure activation
+       return(SIM_ERR_HARDWARE_FAIL);
+      #endif
+    #endif	 // ANLG_FAM == 1, 2, 3
+
+}
+
+
+
+SYS_UWORD8 SIM_Memcpy(SYS_UWORD8 *Buff_target, SYS_UWORD8 Buff_source[], SYS_UWORD16 len)
+{
+    SYS_UWORD16 i;  //unsigned short type counter chosen for copy of 256 bytes
+
+    for (i = 0; i < len; i++)
+          {
+         if (i == RSIMBUFSIZE) 
+          {
+               return (SIM_ERR_BUFF_OVERFL);
+          }
+          else
+	  {
+              (*(Buff_target+i)) = Buff_source[i];
+          }
+    }
+    return (0);
+}
+
+
+
+/*
+ * SIM_SleepStatus
+ * 
+ * Return SIM status for sleep manager
+ * 
+ */
+SYS_BOOL SIM_SleepStatus(void)
+{
+	if ((SIM_sleep_status == SIM_SLEEP_ACT) ||  (SIM_sleep_status == SIM_SLEEP_NONE))
+		return(1);		 // SIM is ready for deep sleep
+	else 
+		return(0);
+}
+
+
+
+
+/*
+* Special lock function to force SIM entity to use adequat SIM Driver
+*/
+void SIM_lock_cr17689(void) {
+}
+
+
+#ifdef SIM_DEBUG_TRACE
+void SIM_dbg_write_trace(SYS_UWORD8 *ptr, SYS_UWORD16 len) {
+   SYS_UWORD16 i;
+   for(i=0;i<len;i++) {
+      if (SIM_dbg_cmd_cmpt == SIM_DBG_CMD)
+	     SIM_dbg_cmd_cmpt = 0;
+	  SIM_dbg_cmd[SIM_dbg_cmd_cmpt++] = ptr[i];
+   }
+}
+#endif
+
+
+
+