?? sim.c
字號:
/*
* 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 "chipset.cfg"
#endif
#include "sys_types.h"
#include "mem.h"
//#include "assert.h"
#include "iq.h"
#include "sim.h"
#include <string.h>
#include "armio.h"
#include "ind_os.h"
#include "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_UWORD8 *lenP, SYS_UWORD8 offset)
{
SYS_UWORD8 sw1, sw2, len;
SYS_UWORD8 verdict;
// Check if all characters were transmitted
if (p->xIn - 1 != p->xOut)
return (SIM_ERR_XMIT);
len = p->rx_index;
*lenP = len - offset;
if (p->expected_data == 256)
{
verdict = SIM_Memcpy(rP, ((p->rbuf) + offset), 255 - offset);
if (verdict != 0)
{
return (verdict);
}
}
else if ((len != 0) && (len >= offset))
{
verdict = SIM_Memcpy(rP, ((p->rbuf) + offset), len - 1 - 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_UWORD8 *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_UWORD8 *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
*/
SYS_UWORD16 SIM_Reset(SIM_CARD *cP)
{
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()) != SIM_OK)
return((SYS_UWORD16)BackValue);
// end of JYT modifications
p->etu9600 = 1075; // old = 239, increase of 450%
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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -