# HG changeset patch # User Michael Spacefalcon # Date 1384738639 0 # Node ID 5e0e41cd7c9f7bdb879804ae2de7d8c50adbf331 # Parent 595192258bc94ee76c689970a72b07a43da080ba gsm-fw/bsp/sim*.c: initial import from the Leonardo semi-src diff -r 595192258bc9 -r 5e0e41cd7c9f gsm-fw/bsp/sim.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/bsp/sim.c Mon Nov 18 01:37:19 2013 +0000 @@ -0,0 +1,3187 @@ +/* + * 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 +#include "armio/armio.h" +#include "ind_os.h" +#include "abb/abb.h" //controls level shifter of ABB + + +//current voltage mode 3V or 5V, or 1.8V +SYS_UWORD8 CurrentVolt; + + + +#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; + + // 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;ixbuf[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;ixbuf[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;ixbuf[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;ixbuf[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;ixbuf[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;ixbuf[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;ixbuf[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;ixbuf[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;ixbuf[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 0 // Dmitriy: removed by TI patch + if (TA1 >= 0x94) //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 + } +#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;iAtrSize;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;iAtrSize;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 +#include "inth/iq.h" +#include "sim.h" + + +#ifdef SIM_DEBUG_TRACE +/* working buffer for NULL BYTE */ +extern SYS_UWORD8 SIM_dbg_null[]; +/* Nucleus variable given the current number of TDMA frames */ +extern SYS_UWORD32 IQ_FrameCount; +/* working variable to calculate the TDMA ecart */ +extern SYS_UWORD16 SIM_dbg_tdma_diff; +/* working variable storing the current number of TDMA frames elapsed */ +SYS_UWORD32 SIM_dbg_local_count; +#endif + +/* + * SIM_IntHandler + * + * Read cause of SIM interrupt : + * + * if receive buffer full, read char + * if transmitter empty, change direction, transmit a dummy char + * + */ +void SIM_IntHandler(void) +{ + volatile unsigned short it, i, stat, conf1; + volatile SYS_UWORD8 ins; + volatile SYS_UWORD8 rx; + volatile SYS_UWORD8 nack; + volatile SYS_UWORD8 nack1; + + + SIM_PORT *p; + + p = &(Sim[0]); + + p->rxParityErr = 0; + it = p->c->it; + + if ((it & SIM_IT_ITRX) && !(p->c->maskit & SIM_MASK_RX)) // int on reception + { + stat = p->c->rx; + conf1 = p->conf1; + +#ifdef SIM_DEBUG_TRACE + if ((IQ_FrameCount - SIM_dbg_local_count) > SIM_dbg_tdma_diff) { + SIM_dbg_tdma_diff = IQ_FrameCount - SIM_dbg_local_count; + } + SIM_dbg_local_count = IQ_FrameCount; +#endif + + // Check if reception parity is enable + if (((conf1 & SIM_CONF1_CHKPAR) && ((stat & SIM_DRX_STATRXPAR) != 0))\ + || ((conf1 & SIM_CONF1_CHKPAR) == 0)) + { + rx = (SYS_UWORD8) (stat & 0x00FF); + ins = p->xbuf[1] & p->hw_mask; + nack = (~p->xbuf[1]) & p->hw_mask; + + switch (p->moderx) + { + case 0: //mode of normal reception without proc char (like PTS proc) + p->rbuf[p->rx_index++] = rx; + break; + + case 1: //mode wait for ACK + if ((rx & p->hw_mask) == ins) + { + p->moderx = 2; + } + else if ((rx & p->hw_mask) == nack) + { + p->moderx = 4; + } + else if (((rx & 0xF0) == 0x60) || ((rx & 0xF0) == 0x90)) + { + if (rx != 0x60) //in case of error code (SW1/SW2) returned by sim card + { + p->rSW12[p->SWcount++] = rx; + p->moderx = 5; + } + else + { + p->null_received = 1; +#ifdef SIM_DEBUG_TRACE + SIM_dbg_null[0]++; +#endif + } + } + else + { + p->errorSIM = SIM_ERR_ABNORMAL_CASE2; + } + //if rx = 0x60 wait for ACK + break; + + case 2: //mode reception by block + p->rbuf[p->rx_index++] = rx; + + if(p->expected_data == 256) + { + if (p->rx_index == 0) + { + p->moderx = 5; + } + } + else + { + if (p->rx_index == p->expected_data) + { + p->moderx = 5; + } + } + break; + + case 3: //mode reception char by char. reception of proc char + if ((rx & p->hw_mask) == ins) + { + p->moderx = 2; + } + else if ((rx & p->hw_mask) == nack) + { + p->moderx = 4; + } //if rx = 0x60 wait for ACK + else if (rx == 0x60) + { + p->null_received == 1; +#ifdef SIM_DEBUG_TRACE + SIM_dbg_null[1]++; +#endif + } + + break; + + case 4: //mode reception char by char. reception of data + p->rbuf[p->rx_index++] = rx; + p->moderx = 3; //switch to receive proc char mode + + if(p->expected_data == 256) + { + if (p->rx_index == 0) + { + p->moderx = 5; + } + } + else + { + if (p->rx_index == p->expected_data) + { + p->moderx = 5; + } + } + break; + + case 5: //mode wait for procedure character except NULL + if ((rx != 0x60) || (p->SWcount != 0)) //treat NULL character only if arriving before SW1 SW2 + { + p->rSW12[p->SWcount++] = rx; + } + else + { + p->null_received = 1; +#ifdef SIM_DEBUG_TRACE + SIM_dbg_null[2]++; +#endif + } + + + break; + + case 6: //give the acknowledge char + if (((rx & 0xF0) == 0x60) || ((rx & 0xF0) == 0x90)) + { + if (rx != 0x60) //in case of error code (SW1/SW2) returned by sim card + { + p->rSW12[p->SWcount++] = rx; + p->moderx = 5; + } + else + { + p->null_received = 1; +#ifdef SIM_DEBUG_TRACE + SIM_dbg_null[3]++; +#endif + } + } + else + { + p->ack = rx; + } + } + } + else + { + p->rxParityErr = 1; + } + } + + if ((it & SIM_IT_ITTX) && !(p->c->maskit & SIM_MASK_TX)) + { +#ifdef SIM_DEBUG_TRACE + SIM_dbg_local_count = IQ_FrameCount; +#endif + // check the transmit parity + stat = p->c->stat; + + + if ((stat & SIM_STAT_TXPAR) || ((p->conf1 & SIM_CONF1_CHKPAR) == 0)) //parity disable + { + if (p->xOut != (p->xIn - 1)) //if only one char transmitted (already transmitted) + { //just need to have confirmation of reception + if (p->xOut == (p->xIn - 2)) + { + p->xOut++; + p->c->tx = *(p->xOut); // transmit + + p->conf1 &= ~SIM_CONF1_TXRX; // return the direction + p->c->conf1 = p->conf1; + } + + if (p->xOut < (p->xIn - 2)) + { + p->xOut++; + p->c->tx = *(p->xOut); // transmit + } + } + } + else + { + p->c->tx = *(p->xOut); // transmit same char + p->txParityErr++; // count number of transmit parity errors + } + + } + + // Handle errors + if ((it & SIM_IT_ITOV) && !(p->c->maskit & SIM_MASK_OV)) + { + p->errorSIM = SIM_ERR_OVF; + + } + if ((it & SIM_IT_WT) && !(p->c->maskit & SIM_MASK_WT)) + { + p->errorSIM = SIM_ERR_READ; + } + + // Reset the card in case of NATR to let the program continue + if ((it & SIM_IT_NATR) && !(p->c->maskit & SIM_MASK_NATR)) + { + p->c->cmd = SIM_CMD_STOP; + p->errorSIM = SIM_ERR_NATR; + } + +#if ((CHIPSET == 2) || (CHIPSET == 3)) + // SIM card insertion / extraction + if ((it & SIM_IT_CD) && !(p->c->maskit & SIM_MASK_CD)) + { + stat = p->c->stat; + if ((stat & SIM_STAT_CD) != SIM_STAT_CD) + { + (p->RemoveFunc)(); + p->errorSIM = SIM_ERR_NOCARD; + } + } +#endif +} + +#if ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12)) + /* + * SIM_CD_IntHandler + * + * Read cause of SIM interrupt : + * + */ + void SIM_CD_IntHandler(void) + { + volatile unsigned short it_cd, stat; + SIM_PORT *p; + + p = &(Sim[0]); + + p->rxParityErr = 0; + it_cd = p->c->it_cd; + + // SIM card insertion / extraction + if ((it_cd & SIM_IT_CD) && !(p->c->maskit & SIM_MASK_CD)) + { + stat = p->c->stat; + if ((stat & SIM_STAT_CD) != SIM_STAT_CD) + { + (p->RemoveFunc)(); + p->errorSIM = SIM_ERR_NOCARD; + } + } +} +#endif + + +// to force this module to be linked +SYS_UWORD16 SIM_Dummy(void) +{ + +}