⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sim.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * 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 + -