FreeCalypso > hg > fc-selenite
view src/cs/drivers/drv_app/sim/sim.c @ 196:5f3544fc0308
AT@SPENH brought over from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 24 May 2020 19:46:18 +0000 |
parents | 2863e5e4af4f |
children |
line wrap: on
line source
/* * 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