]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/i2c.c
fix 'hf iclass sim':
[proxmark3-svn] / armsrc / i2c.c
index 721b4b2e03e733cd0619bd4239643c9bf3efc161..51513114d3e81494e626714a24ca0388b37e32d0 100644 (file)
@@ -8,11 +8,22 @@
 //-----------------------------------------------------------------------------
 // The main i2c code, for communications with smart card module
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // The main i2c code, for communications with smart card module
 //-----------------------------------------------------------------------------
+
 #include "i2c.h"
 #include "i2c.h"
-#include "mifareutil.h" //for mf_dbglevel
+
+#include <stdint.h>
+#include <stdbool.h>
 #include "string.h"  //for memset memcmp
 #include "string.h"  //for memset memcmp
+#include "proxmark3.h"
+#include "mifareutil.h" // for MF_DBGLEVEL
+#include "BigBuf.h"
+#include "apps.h"
+
+#ifdef WITH_SMARTCARD
+#include "smartcard.h"
+#endif
+
 
 
-//     ¶¨ÒåÁ¬½ÓÒý½Å
 #define GPIO_RST  AT91C_PIO_PA1
 #define GPIO_SCL  AT91C_PIO_PA5
 #define GPIO_SDA  AT91C_PIO_PA7
 #define GPIO_RST  AT91C_PIO_PA1
 #define GPIO_SCL  AT91C_PIO_PA5
 #define GPIO_SDA  AT91C_PIO_PA7
 
 #define I2C_ERROR  "I2C_WaitAck Error" 
 
 
 #define I2C_ERROR  "I2C_WaitAck Error" 
 
-volatile unsigned long c;
+static volatile unsigned long c;
 
 //     Ö±½ÓʹÓÃÑ­»·À´ÑÓʱ£¬Ò»¸öÑ­»· 6 ÌõÖ¸Á48M£¬ Delay=1 ´ó¸ÅΪ 200kbps
 // timer.
 // I2CSpinDelayClk(4) = 12.31us
 // I2CSpinDelayClk(1) = 3.07us
 
 //     Ö±½ÓʹÓÃÑ­»·À´ÑÓʱ£¬Ò»¸öÑ­»· 6 ÌõÖ¸Á48M£¬ Delay=1 ´ó¸ÅΪ 200kbps
 // timer.
 // I2CSpinDelayClk(4) = 12.31us
 // I2CSpinDelayClk(1) = 3.07us
-void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
+static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
        for (c = delay * 2; c; c--) {};
 }
 
        for (c = delay * 2; c; c--) {};
 }
 
-//     Í¨Ñ¶ÑÓ³Ùº¯Êý     communication delay function   
+// communication delay functions
 #define I2C_DELAY_1CLK    I2CSpinDelayClk(1)
 #define I2C_DELAY_2CLK    I2CSpinDelayClk(2)
 #define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
 
 #define I2C_DELAY_1CLK    I2CSpinDelayClk(1)
 #define I2C_DELAY_2CLK    I2CSpinDelayClk(2)
 #define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
 
-
 #define  ISO7618_MAX_FRAME 255
 
 #define  ISO7618_MAX_FRAME 255
 
-void I2C_init(void) {
-       // ÅäÖø´Î»Òý½Å£¬¹Ø±ÕÉÏÀ­£¬ÍÆÍìÊä³ö£¬Ä¬Èϸß
-       // Configure reset pin, close up pull up, push-pull output, default high
-       AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;
-       AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;
+// try i2c bus recovery at 100kHz = 5uS high, 5uS low
+static void I2C_recovery(void) {
+
+       DbpString("Performing i2c bus recovery");       
+                       
+       // reset I2C
+       SDA_H; SCL_H;
+       
+        //9nth cycle acts as NACK
+       for (int i = 0; i < 10; i++)  {
+               SCL_H; WaitUS(5);
+               SCL_L; WaitUS(5);
+       }
+       
+    //a STOP signal (SDA from low to high while CLK is high)   
+       SDA_L; WaitUS(5);
+       SCL_H; WaitUS(2);
+       SDA_H; WaitUS(2);
+       
+       bool isok = (SCL_read && SDA_read); 
+    if (!SDA_read)
+               DbpString("I2C bus recovery  error: SDA still LOW");
+       if (!SCL_read)
+               DbpString("I2C bus recovery  error: SCL still LOW");
+       if (isok)
+               DbpString("I2C bus recovery complete");
+}
+
+static void I2C_init(void) {
+       // Configure reset pin
+       AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;  // disable pull up resistor
+       AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;   // push-pull output (multidriver disabled)
 
 
-       // ÅäÖàI2C Òý½Å£¬¿ªÆôÉÏÀ­£¬¿ªÂ©Êä³ö
-       // Configure I2C pin, open up, open leakage
-       AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA);  // ´ò¿ªÉÏÀ­  Open up the pull up
-       AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA);
+       // Configure SCL and SDA pins
+       AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA);  // enable pull up resistor
+       AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA);   // open drain output (multidriver enabled) - requires external pull up resistor
 
 
-       // Ä¬ÈÏÈý¸ùÏßÈ«²¿À­¸ß
-       // default three lines all pull up
+       // set all three outputs to high
        AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
 
        AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
 
-       // ÔÊÐíÊä³ö
-       // allow output
+       // configure all three pins as output, controlled by PIOA
        AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
        AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
        AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
        AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
-}
 
 
+       bool isok =  (SCL_read && SDA_read); 
+       if ( !isok )
+               I2C_recovery();
+       
+}
 
 
-// ÉèÖø´Î»×´Ì¬
 // set the reset state
 // set the reset state
-void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
+static void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
        if (LineRST)
                HIGH(GPIO_RST);
        else
        if (LineRST)
                HIGH(GPIO_RST);
        else
@@ -86,31 +123,21 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
                LOW(GPIO_SDA);
 }
 
                LOW(GPIO_SDA);
 }
 
-// ¸´Î»½øÈëÖ÷³ÌÐò
 // Reset the SIM_Adapter, then  enter the main program
 // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
 // Reset the SIM_Adapter, then  enter the main program
 // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
-void I2C_Reset_EnterMainProgram(void) {
-       I2C_SetResetStatus(0, 0, 0);    // À­µÍ¸´Î»Ïß
-       SpinDelay(30);
-       I2C_SetResetStatus(1, 0, 0);    // ½â³ý¸´Î»
-       SpinDelay(30);
-       I2C_SetResetStatus(1, 1, 1);    // À­¸ßÊý¾ÝÏß
-       SpinDelay(10);
-}
-
-// ¸´Î»½øÈëÒýµ¼Ä£Ê½
-// Reset the SIM_Adapter, then enter the bootloader program
-// Reserve£ºFor firmware update.
-void I2C_Reset_EnterBootloader(void) {
-       I2C_SetResetStatus(0, 1, 1);    // À­µÍ¸´Î»Ïß
-       SpinDelay(100);
-       I2C_SetResetStatus(1, 1, 1);    // ½â³ý¸´Î»
-       SpinDelay(10);
+static void I2C_Reset_EnterMainProgram(void) {
+       StartTicks();
+       I2C_init();
+       I2C_SetResetStatus(0, 0, 0);
+       WaitMS(30);
+       I2C_SetResetStatus(1, 0, 0);
+       WaitMS(30);
+       I2C_SetResetStatus(1, 1, 1);
+       WaitMS(10);
 }
 
 }
 
-//     µÈ´ýʱÖÓ±ä¸ß    
 // Wait for the clock to go High.      
 // Wait for the clock to go High.      
-bool WaitSCL_H_delay(uint32_t delay) {
+static bool WaitSCL_H_delay(uint32_t delay) {
        while (delay--) {
                if (SCL_read) {
                        return true;
        while (delay--) {
                if (SCL_read) {
                        return true;
@@ -120,26 +147,26 @@ bool WaitSCL_H_delay(uint32_t delay) {
        return false;
 }
 
        return false;
 }
 
-// 5000 * 3.07us = 15350us. 15.35ms
-bool WaitSCL_H(void) {
-       return WaitSCL_H_delay(5000);
+// 15000 * 3.07us = 46050us. 46.05ms
+static bool WaitSCL_H(void) {
+       return WaitSCL_H_delay(15000);
 }
 
 }
 
-// Wait max 300ms or until SCL goes LOW.
-// Which ever comes first
-bool WaitSCL_L_300ms(void) {
-       volatile uint16_t delay = 300;
-       while ( delay-- ) {
-               // exit on SCL LOW
-               if (!SCL_read)
+bool WaitSCL_L_delay(uint32_t delay) {
+       while (delay--) {
+               if (!SCL_read) {
                        return true;
                        return true;
-
-               SpinDelay(1);
+               }
+               I2C_DELAY_1CLK;         
        }
        }
-       return (delay == 0);
+       return false;   
 }
 
 }
 
-bool I2C_Start(void) {
+bool WaitSCL_L(void) {
+       return WaitSCL_L_delay(15000);
+}
+
+static bool I2C_Start(void) {
 
        I2C_DELAY_XCLK(4);
        SDA_H; I2C_DELAY_1CLK;
 
        I2C_DELAY_XCLK(4);
        SDA_H; I2C_DELAY_1CLK;
@@ -155,22 +182,8 @@ bool I2C_Start(void) {
        return true;
 }
 
        return true;
 }
 
-bool I2C_WaitForSim() {
-       // variable delay here.
-       if (!WaitSCL_L_300ms())
-               return false;
-
-       // 8051 speaks with smart card.
-       // 1000*50*3.07 = 153.5ms
-       // 1byte transfer == 1ms
-       if (!WaitSCL_H_delay(2000*50) )
-               return false;
-
-       return true;
-}
-
 // send i2c STOP
 // send i2c STOP
-void I2C_Stop(void) {
+static void I2C_Stop(void) {
        SCL_L; I2C_DELAY_2CLK;
        SDA_L; I2C_DELAY_2CLK;
        SCL_H; I2C_DELAY_2CLK;
        SCL_L; I2C_DELAY_2CLK;
        SDA_L; I2C_DELAY_2CLK;
        SCL_H; I2C_DELAY_2CLK;
@@ -179,29 +192,14 @@ void I2C_Stop(void) {
        I2C_DELAY_XCLK(8);
 }
 
        I2C_DELAY_XCLK(8);
 }
 
-// Send i2c ACK
-void I2C_Ack(void) {
-       SCL_L; I2C_DELAY_2CLK;
-       SDA_L; I2C_DELAY_2CLK;
-       SCL_H; I2C_DELAY_2CLK;
-       SCL_L; I2C_DELAY_2CLK;
-}
-
-// Send i2c NACK
-void I2C_NoAck(void) {
-       SCL_L; I2C_DELAY_2CLK;
-       SDA_H; I2C_DELAY_2CLK;
-       SCL_H; I2C_DELAY_2CLK;
-       SCL_L; I2C_DELAY_2CLK;
-}
-
-bool I2C_WaitAck(void) {
+static bool I2C_WaitAck(void) {
        SCL_L; I2C_DELAY_1CLK;
        SDA_H; I2C_DELAY_1CLK;
        SCL_H;
        if (!WaitSCL_H())
                return false;
 
        SCL_L; I2C_DELAY_1CLK;
        SDA_H; I2C_DELAY_1CLK;
        SCL_H;
        if (!WaitSCL_H())
                return false;
 
+       I2C_DELAY_2CLK;
        I2C_DELAY_2CLK;
        if (SDA_read) {
                SCL_L;
        I2C_DELAY_2CLK;
        if (SDA_read) {
                SCL_L;
@@ -211,11 +209,12 @@ bool I2C_WaitAck(void) {
        return true;
 }
 
        return true;
 }
 
-void I2C_SendByte(uint8_t data) {
-       uint8_t i = 8;
+static void I2C_SendByte(uint8_t data) {
+       uint8_t bits = 8;
 
 
-       while (i--) {
-               SCL_L; I2C_DELAY_1CLK;
+       while (bits--) {
+               SCL_L; 
+               I2C_DELAY_1CLK;
 
                if (data & 0x80)
                        SDA_H;
 
                if (data & 0x80)
                        SDA_H;
@@ -223,6 +222,7 @@ void I2C_SendByte(uint8_t data) {
                        SDA_L;
 
                data <<= 1;
                        SDA_L;
 
                data <<= 1;
+
                I2C_DELAY_1CLK;
 
                SCL_H;
                I2C_DELAY_1CLK;
 
                SCL_H;
@@ -234,18 +234,91 @@ void I2C_SendByte(uint8_t data) {
        SCL_L;
 }
 
        SCL_L;
 }
 
-uint8_t I2C_ReadByte(void) {
-       uint8_t i = 8, b = 0;
+bool I2C_is_available(void) {
+       I2C_Reset_EnterMainProgram();
+       if (!I2C_Start())  // some other device is active on the bus
+               return true;
+       I2C_SendByte(I2C_DEVICE_ADDRESS_MAIN & 0xFE);
+       if (!I2C_WaitAck()) {  // no response from smartcard reader
+               I2C_Stop();
+               return false;
+       }
+       I2C_Stop();
+       return true;
+}
+
+#ifdef WITH_SMARTCARD
+// Reset the SIM_Adapter, then enter the bootloader program
+// Reserve£ºFor firmware update.
+static void I2C_Reset_EnterBootloader(void) {
+       I2C_SetResetStatus(0, 1, 1);
+       WaitMS(100);
+       I2C_SetResetStatus(1, 1, 1);
+       WaitMS(10);
+}
+
+// Wait max 1800ms or until SCL goes LOW.
+// It timeout reading response from card
+// Which ever comes first
+bool WaitSCL_L_timeout(void){
+       volatile uint16_t delay = 1800;
+       while ( delay-- ) {
+               // exit on SCL LOW
+               if (!SCL_read)
+                       return true;
+
+               WaitMS(1);
+       }
+       return (delay == 0);
+}
+
+static bool I2C_WaitForSim() {
+       // wait for data from card
+       if (!WaitSCL_L_timeout())
+               return false;
+
+       // 8051 speaks with smart card.
+       // 1000*50*3.07 = 153.5ms
+       // 1byte transfer == 1ms with max frame being 256bytes
+       if (!WaitSCL_H_delay(10 * 1000 * 50))
+               return false;
+
+       return true;
+}
+
+// Send i2c ACK
+static void I2C_Ack(void) {
+       SCL_L; I2C_DELAY_2CLK;
+       SDA_L; I2C_DELAY_2CLK;
+       SCL_H; I2C_DELAY_2CLK;
+       if (!WaitSCL_H()) return;
+       SCL_L; I2C_DELAY_2CLK;
+}
+
+// Send i2c NACK
+static void I2C_NoAck(void) {
+       SCL_L; I2C_DELAY_2CLK;
+       SDA_H; I2C_DELAY_2CLK;
+       SCL_H; I2C_DELAY_2CLK;
+       if (!WaitSCL_H()) return;
+       SCL_L; I2C_DELAY_2CLK;
+}
+
+static int16_t I2C_ReadByte(void) {
+       uint8_t bits = 8, b = 0;
 
        SDA_H;
 
        SDA_H;
-       while (i--) {
+       while (bits--) {
                b <<= 1;
                b <<= 1;
-               SCL_L; I2C_DELAY_2CLK;
+               SCL_L; 
+               if (!WaitSCL_L()) return -2;
+               
+               I2C_DELAY_1CLK;
+
                SCL_H;
                SCL_H;
-               if (!WaitSCL_H())
-                       return 0;
+               if (!WaitSCL_H()) return -1;
 
 
-               I2C_DELAY_2CLK;
+               I2C_DELAY_1CLK;
                if (SDA_read)
                        b |= 0x01;
        }
                if (SDA_read)
                        b |= 0x01;
        }
@@ -254,12 +327,12 @@ uint8_t I2C_ReadByte(void) {
 }
 
 // Sends one byte  ( command to be written, SlaveDevice address)
 }
 
 // Sends one byte  ( command to be written, SlaveDevice address)
-bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
+static bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
        bool bBreak = true;
        do {
                if (!I2C_Start())
                        return false;
        bool bBreak = true;
        do {
                if (!I2C_Start())
                        return false;
-               //[C0]
+               
                I2C_SendByte(device_address & 0xFE);
                if (!I2C_WaitAck())
                        break;
                I2C_SendByte(device_address & 0xFE);
                if (!I2C_WaitAck())
                        break;
@@ -279,9 +352,8 @@ bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
        return true;
 }
 
        return true;
 }
 
-// Ð´Èë1×Ö½ÚÊý¾Ý £¨´ýдÈëÊý¾Ý£¬´ýдÈëµØÖ·£¬Æ÷¼þÀàÐÍ£©
 // Sends 1 byte data (Data to be written, command to be written , SlaveDevice address  ).
 // Sends 1 byte data (Data to be written, command to be written , SlaveDevice address  ).
-bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
+static bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
        bool bBreak = true;
        do {
                if (!I2C_Start())
        bool bBreak = true;
        do {
                if (!I2C_Start())
@@ -310,10 +382,9 @@ bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
        return true;
 }
 
        return true;
 }
 
-//     Ð´Èë1´®Êý¾Ý£¨´ýдÈëÊý×éµØÖ·£¬´ýдÈ볤¶È£¬´ýдÈëµØÖ·£¬Æ÷¼þÀàÐÍ£© 
 //Sends a string of data (Array, length, command to be written , SlaveDevice address  ).
 // len = uint8 (max buffer to write 256bytes)
 //Sends a string of data (Array, length, command to be written , SlaveDevice address  ).
 // len = uint8 (max buffer to write 256bytes)
-bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
+static bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
        bool bBreak = true;
        do {
                if (!I2C_Start())
        bool bBreak = true;
        do {
                if (!I2C_Start())
@@ -349,19 +420,18 @@ bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t dev
        return true;
 }
 
        return true;
 }
 
-// ¶Á³ö1´®Êý¾Ý£¨´æ·Å¶Á³öÊý¾Ý£¬´ý¶Á³ö³¤¶È£¬´ø¶Á³öµØÖ·£¬Æ÷¼þÀàÐÍ£©
 // read 1 strings of data (Data array, Readout length, command to be written , SlaveDevice address  ).
 // len = uint8 (max buffer to read 256bytes)
 // read 1 strings of data (Data array, Readout length, command to be written , SlaveDevice address  ).
 // len = uint8 (max buffer to read 256bytes)
-uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
+static int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
 
        if ( !data || len == 0 )
                return 0;
 
        // extra wait  500us (514us measured)
        // 200us  (xx measured)
 
        if ( !data || len == 0 )
                return 0;
 
        // extra wait  500us (514us measured)
        // 200us  (xx measured)
-       SpinDelayUs(200);
+       WaitUS(600);
        bool bBreak = true;
        bool bBreak = true;
-       uint8_t readcount = 0;
+       uint16_t readcount = 0;
 
        do {
                if (!I2C_Start())
 
        do {
                if (!I2C_Start())
@@ -391,11 +461,14 @@ uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
                return 0;
        }
 
                return 0;
        }
 
-       // reading
        while (len) {
 
        while (len) {
 
-               *data = I2C_ReadByte();
-
+               int16_t tmp = I2C_ReadByte();
+               if ( tmp < 0 )
+                       return tmp;
+               
+               *data = (uint8_t)tmp & 0xFF;
+               
                len--;
 
                // ¶ÁÈ¡µÄµÚÒ»¸ö×Ö½ÚΪºóÐø³¤¶È   
                len--;
 
                // ¶ÁÈ¡µÄµÚÒ»¸ö×Ö½ÚΪºóÐø³¤¶È   
@@ -415,11 +488,12 @@ uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
        }
 
        I2C_Stop();
        }
 
        I2C_Stop();
+       
        // return bytecount - first byte (which is length byte)
        // return bytecount - first byte (which is length byte)
-       return (readcount) ? --readcount : 0;
+       return --readcount;
 }
 
 }
 
-uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
+static int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
        //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP        
        bool bBreak = true;
        uint8_t readcount = 0;
        //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP        
        bool bBreak = true;
        uint8_t readcount = 0;
@@ -434,12 +508,10 @@ uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t
                if (!I2C_WaitAck())
                        break;
 
                if (!I2C_WaitAck())
                        break;
 
-               // msb
                I2C_SendByte(msb);
                if (!I2C_WaitAck())
                        break;
 
                I2C_SendByte(msb);
                if (!I2C_WaitAck())
                        break;
 
-               // lsb
                I2C_SendByte(lsb);
                if (!I2C_WaitAck())
                        break;
                I2C_SendByte(lsb);
                if (!I2C_WaitAck())
                        break;
@@ -461,8 +533,13 @@ uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t
 
        // reading
        while (len) {
 
        // reading
        while (len) {
-               *data = I2C_ReadByte();
-
+               
+               int16_t tmp = I2C_ReadByte();
+               if ( tmp < 0 )
+                       return tmp;
+               
+               *data = (uint8_t)tmp & 0xFF;
+               
                data++;
                readcount++;
                len--;
                data++;
                readcount++;
                len--;
@@ -478,7 +555,7 @@ uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t
        return readcount;
 }
 
        return readcount;
 }
 
-bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
+static bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
        //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP     
        bool bBreak = true;
 
        //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP     
        bool bBreak = true;
 
@@ -491,12 +568,10 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d
                if (!I2C_WaitAck())
                        break;
 
                if (!I2C_WaitAck())
                        break;
 
-               // msb
                I2C_SendByte(msb);
                if (!I2C_WaitAck())
                        break;
 
                I2C_SendByte(msb);
                if (!I2C_WaitAck())
                        break;
 
-               // lsb
                I2C_SendByte(lsb);
                if (!I2C_WaitAck())
                        break;
                I2C_SendByte(lsb);
                if (!I2C_WaitAck())
                        break;
@@ -525,7 +600,6 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d
 void I2C_print_status(void) {
        DbpString("Smart card module (ISO 7816)");
        uint8_t resp[] = {0,0,0,0};
 void I2C_print_status(void) {
        DbpString("Smart card module (ISO 7816)");
        uint8_t resp[] = {0,0,0,0};
-       I2C_init();
        I2C_Reset_EnterMainProgram();
        uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN);
        if ( len > 0 )
        I2C_Reset_EnterMainProgram();
        uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN);
        if ( len > 0 )
@@ -534,47 +608,57 @@ void I2C_print_status(void) {
                DbpString("  version.................FAILED");
 }
 
                DbpString("  version.................FAILED");
 }
 
-bool GetATR(smart_card_atr_t *card_ptr) {
+// Will read response from smart card module,  retries 3 times to get the data.
+static bool sc_rx_bytes(uint8_t* dest, uint8_t *destlen) {
+       uint8_t i = 3;
+       int16_t len = 0;
+       while (i--) {
+               
+               I2C_WaitForSim();
+       
+               len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
+               
+               if ( len > 1 ){
+                       break;
+               } else if ( len == 1 ) {
+                       continue;
+               } else if ( len <= 0 ) {
+                       return false;   
+               } 
+       }
+       // after three
+       if ( len <= 1 )
+               return false;
+       
+       *destlen = (uint8_t)len & 0xFF;
+       return true;
+}
+
+static bool GetATR(smart_card_atr_t *card_ptr) {
 
 
-       // clear 
-       if ( card_ptr ) {
-               card_ptr->atr_len = 0;
-               memset(card_ptr->atr, 0, sizeof(card_ptr->atr));
+       if ( !card_ptr ) {
+               return false;
        }
 
        }
 
+       card_ptr->atr_len = 0;
+       memset(card_ptr->atr, 0, sizeof(card_ptr->atr));
+
        // Send ATR
        // start [C0 01] stop start C1 len aa bb cc stop]
        I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN);
        // Send ATR
        // start [C0 01] stop start C1 len aa bb cc stop]
        I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN);
-       uint8_t cmd[1] = {1};
-       LogTrace(cmd, 1, 0, 0, NULL, true);
 
 
-       //wait for sim card to answer.
+       // wait for sim card to answer.
+       // 1byte = 1ms, max frame 256bytes. Should wait 256ms at least just in case.
        if (!I2C_WaitForSim()) 
                return false;
 
        if (!I2C_WaitForSim()) 
                return false;
 
-       // read answer
-       uint8_t len = I2C_BufferRead(card_ptr->atr, sizeof(card_ptr->atr), I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
-
-       if ( len == 0 )
+       // read bytes from module
+       uint8_t len = sizeof(card_ptr->atr);
+       if ( !sc_rx_bytes(card_ptr->atr, &len) )                
                return false;
 
                return false;
 
-       // for some reason we only get first byte of atr, if that is so, send dummy command to retrieve the rest of the atr 
-       if (len == 1) {
-
-               uint8_t data[1] = {0};
-               I2C_BufferWrite(data, len, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN);
-
-               if ( !I2C_WaitForSim() )
-                       return false;
-
-               uint8_t len2 = I2C_BufferRead(card_ptr->atr + len, sizeof(card_ptr->atr) - len, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
-               len = len + len2;
-       }
-
-       if ( card_ptr ) {
-               card_ptr->atr_len = len;
-               LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
-       }
+       card_ptr->atr_len = len;
+       LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
 
        return true;
 }
 
        return true;
 }
@@ -584,7 +668,6 @@ void SmartCardAtr(void) {
        LED_D_ON();
        clear_trace();
        set_tracing(true);
        LED_D_ON();
        clear_trace();
        set_tracing(true);
-       I2C_init();
        I2C_Reset_EnterMainProgram();
        bool isOK = GetATR( &card );
        cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
        I2C_Reset_EnterMainProgram();
        bool isOK = GetATR( &card );
        cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
@@ -607,10 +690,9 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) {
 
        if ((flags & SC_CONNECT)) {     
 
 
        if ((flags & SC_CONNECT)) {     
 
-               I2C_init();
                I2C_Reset_EnterMainProgram();
 
                I2C_Reset_EnterMainProgram();
 
-               if ( !(flags & SC_NO_SELECT) ) {
+               if ((flags & SC_SELECT)) {
                        smart_card_atr_t card;
                        bool gotATR = GetATR( &card );
                        //cmd_send(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
                        smart_card_atr_t card;
                        bool gotATR = GetATR( &card );
                        //cmd_send(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
@@ -619,23 +701,28 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) {
                }
        }
 
                }
        }
 
-       if ((flags & SC_RAW)) {
+       if ((flags & SC_RAW) || (flags & SC_RAW_T0)) {
 
                LogTrace(data, arg1, 0, 0, NULL, true);
 
                // Send raw bytes
                // asBytes = A0 A4 00 00 02
                // arg1 = len 5
 
                LogTrace(data, arg1, 0, 0, NULL, true);
 
                // Send raw bytes
                // asBytes = A0 A4 00 00 02
                // arg1 = len 5
-               I2C_BufferWrite(data, arg1, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN);
-
-               if ( !I2C_WaitForSim() )
-                       goto OUT;
-
-               len = I2C_BufferRead(resp, ISO7618_MAX_FRAME, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
-               LogTrace(resp, len, 0, 0, NULL, false);
+               bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN);
+               if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
+
+               // read bytes from module
+               len = ISO7618_MAX_FRAME;
+               res = sc_rx_bytes(resp, &len);
+               if ( res ) {
+                       LogTrace(resp, len, 0, 0, NULL, false);
+               } else {
+                       len = 0;
+               }
        }
 OUT:
        cmd_send(CMD_ACK, len, 0, 0, resp, len);
        }
 OUT:
        cmd_send(CMD_ACK, len, 0, 0, resp, len);
+       BigBuf_free();
        set_tracing(false);
        LEDsoff();
 }
        set_tracing(false);
        LEDsoff();
 }
@@ -648,11 +735,10 @@ void SmartCardUpgrade(uint64_t arg0) {
        // write.   Sector0,  with 11,22,33,44
        // erase is 128bytes, and takes 50ms to execute
 
        // write.   Sector0,  with 11,22,33,44
        // erase is 128bytes, and takes 50ms to execute
 
-       I2C_init();
        I2C_Reset_EnterBootloader();
 
        bool isOK = true;
        I2C_Reset_EnterBootloader();
 
        bool isOK = true;
-       uint8_t res = 0;
+       int16_t res = 0;
        uint16_t length = arg0;
        uint16_t pos = 0;
        uint8_t *fwdata = BigBuf_get_addr();
        uint16_t length = arg0;
        uint16_t pos = 0;
        uint8_t *fwdata = BigBuf_get_addr();
@@ -676,11 +762,11 @@ void SmartCardUpgrade(uint64_t arg0) {
                }
 
                // writing takes time.
                }
 
                // writing takes time.
-               SpinDelay(50);
+               WaitMS(50);
 
                // read
                res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
 
                // read
                res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
-               if ( res == 0) {
+               if ( res <= 0) {
                        DbpString("Reading back failed");
                        isOK = false;
                        break;
                        DbpString("Reading back failed");
                        isOK = false;
                        break;
@@ -698,6 +784,7 @@ void SmartCardUpgrade(uint64_t arg0) {
        }
        cmd_send(CMD_ACK, isOK, pos, 0, 0, 0);
        LED_C_OFF();
        }
        cmd_send(CMD_ACK, isOK, pos, 0, 0, 0);
        LED_C_OFF();
+       BigBuf_free();  
 }
 
 // unfinished (or not needed?)
 }
 
 // unfinished (or not needed?)
@@ -707,7 +794,6 @@ void SmartCardUpgrade(uint64_t arg0) {
 void SmartCardSetClock(uint64_t arg0) {
        LED_D_ON();
        set_tracing(true);
 void SmartCardSetClock(uint64_t arg0) {
        LED_D_ON();
        set_tracing(true);
-       I2C_init();
        I2C_Reset_EnterMainProgram();
 
        // Send SIM CLC
        I2C_Reset_EnterMainProgram();
 
        // Send SIM CLC
@@ -718,3 +804,5 @@ void SmartCardSetClock(uint64_t arg0) {
        set_tracing(false);
        LEDsoff();
 }
        set_tracing(false);
        LEDsoff();
 }
+
+#endif
\ No newline at end of file
Impressum, Datenschutz