From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001
From: Harald Welte <laforge@gnumonks.org>
Date: Mon, 4 Jul 2011 20:52:54 +0200
Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011

it's sad to see that atmel doesn't publish their svn repo or has
a centralized location or even puts proper version/release info
into the library itself
---
 components/iso7816/iso7816.dir |  45 +++
 components/iso7816/iso7816_4.c | 620 +++++++++++++++++++++++++++++++++++++++++
 components/iso7816/iso7816_4.h |  87 ++++++
 3 files changed, 752 insertions(+)
 create mode 100644 components/iso7816/iso7816.dir
 create mode 100644 components/iso7816/iso7816_4.c
 create mode 100644 components/iso7816/iso7816_4.h

(limited to 'components/iso7816')

diff --git a/components/iso7816/iso7816.dir b/components/iso7816/iso7816.dir
new file mode 100644
index 0000000..433a418
--- /dev/null
+++ b/components/iso7816/iso7816.dir
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !Purpose
+///
+/// This directory contains an API for ISO 7816-3 and ISO 7816-4
+///
+/// !Contents
+///
+/// The definitions and functions provided are dispatched inside a number of
+/// files:
+///    - iso7816_4.h api definition for iso 7816-4
+///    - iso7816_4.c driver iso 7816-4
+/// 
+//------------------------------------------------------------------------------
+
diff --git a/components/iso7816/iso7816_4.c b/components/iso7816/iso7816_4.c
new file mode 100644
index 0000000..7731dff
--- /dev/null
+++ b/components/iso7816/iso7816_4.c
@@ -0,0 +1,620 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+/// 
+/// ISO 7816 driver
+/// 
+/// !Usage
+/// 
+/// Explanation on the usage of the code made available through the header file.
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <usart/usart.h>
+#include <utility/trace.h>
+#include <pio/pio.h>
+#include "iso7816_4.h"
+
+//------------------------------------------------------------------------------
+//         Definitions
+//------------------------------------------------------------------------------
+/// Case for APDU commands
+#define CASE1  1
+#define CASE2  2
+#define CASE3  3
+
+/// Flip flop for send and receive char
+#define USART_SEND 0
+#define USART_RCV  1
+
+//------------------------------------------------------------------------------
+//         Internal variables
+//------------------------------------------------------------------------------
+/// Variable for state of send and receive froom USART
+static unsigned char StateUsartGlobal = USART_RCV;
+/// Pin reset master card
+static Pin st_pinIso7816RstMC;
+
+//-----------------------------------------------------------------------------
+//         Internal functions
+//-----------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Get a character from ISO7816
+/// \param pCharToReceive Pointer for store the received char
+/// \return 0: if timeout else status of US_CSR
+//------------------------------------------------------------------------------
+static unsigned int ISO7816_GetChar( unsigned char *pCharToReceive )
+{
+    unsigned int status;
+    unsigned int timeout=0;
+
+    if( StateUsartGlobal == USART_SEND ) {
+        while((AT91C_BASE_US0->US_CSR & AT91C_US_TXEMPTY) == 0) {}
+        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA | AT91C_US_RSTIT | AT91C_US_RSTNACK;
+        StateUsartGlobal = USART_RCV;
+    }
+
+    // Wait USART ready for reception
+    while( ((AT91C_BASE_US0->US_CSR & AT91C_US_RXRDY) == 0) ) {
+        if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
+            TRACE_DEBUG("TimeOut\n\r");
+            return( 0 );
+        }
+    }
+
+    TRACE_DEBUG("T: %d\n\r", timeout);
+
+
+    // At least one complete character has been received and US_RHR has not yet been read.
+
+    // Get a char
+    *pCharToReceive = ((AT91C_BASE_US0->US_RHR) & 0xFF);
+
+    status = (AT91C_BASE_US0->US_CSR&(AT91C_US_OVRE|AT91C_US_FRAME|
+                                      AT91C_US_PARE|AT91C_US_TIMEOUT|AT91C_US_NACK|
+                                      (1<<10)));
+
+    if (status != 0 ) {
+       // TRACE_DEBUG("R:0x%X\n\r", status);
+        TRACE_DEBUG("R:0x%X\n\r", AT91C_BASE_US0->US_CSR);
+        TRACE_DEBUG("Nb:0x%X\n\r", AT91C_BASE_US0->US_NER );
+        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA;
+    }
+
+    // Return status
+    return( status );
+}
+
+
+//------------------------------------------------------------------------------
+/// Send a char to ISO7816
+/// \param CharToSend char to be send
+/// \return status of US_CSR
+//------------------------------------------------------------------------------
+static unsigned int ISO7816_SendChar( unsigned char CharToSend )
+{
+    unsigned int status;
+
+    if( StateUsartGlobal == USART_RCV ) {
+        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA | AT91C_US_RSTIT | AT91C_US_RSTNACK;
+        StateUsartGlobal = USART_SEND;
+    }
+
+    // Wait USART ready for transmit
+    while((AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY) == 0)  {}
+    // There is no character in the US_THR
+
+    // Transmit a char
+    AT91C_BASE_US0->US_THR = CharToSend;
+
+    status = (AT91C_BASE_US0->US_CSR&(AT91C_US_OVRE|AT91C_US_FRAME|
+                                      AT91C_US_PARE|AT91C_US_TIMEOUT|AT91C_US_NACK|
+                                      (1<<10)));
+
+    if (status != 0 ) {
+        TRACE_DEBUG("E:0x%X\n\r", AT91C_BASE_US0->US_CSR);
+        TRACE_DEBUG("Nb:0x%X\n\r", AT91C_BASE_US0->US_NER );
+        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA;
+    }
+
+    // Return status
+    return( status );
+}
+
+
+//------------------------------------------------------------------------------
+/// Iso 7816 ICC power on
+//------------------------------------------------------------------------------
+static void ISO7816_IccPowerOn( void )
+{
+    // Set RESET Master Card
+    PIO_Set(&st_pinIso7816RstMC);
+}
+
+//-----------------------------------------------------------------------------
+//         Exported functions
+//-----------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Iso 7816 ICC power off
+//------------------------------------------------------------------------------
+void ISO7816_IccPowerOff( void )
+{
+    // Clear RESET Master Card
+    PIO_Clear(&st_pinIso7816RstMC);
+}
+
+//------------------------------------------------------------------------------
+/// Transfert Block TPDU T=0
+/// \param pAPDU    APDU buffer
+/// \param pMessage Message buffer
+/// \param wLength  Block length
+/// \return         Message index
+//------------------------------------------------------------------------------
+unsigned short ISO7816_XfrBlockTPDU_T0(const unsigned char *pAPDU, 
+                                        unsigned char *pMessage, 
+                                        unsigned short wLength )
+{
+    unsigned short NeNc;
+    unsigned short indexApdu = 4;
+    unsigned short indexMessage = 0;
+    unsigned char SW1 = 0;
+    unsigned char procByte;
+    unsigned char cmdCase;
+
+    TRACE_DEBUG("pAPDU[0]=0x%X\n\r",pAPDU[0]);
+    TRACE_DEBUG("pAPDU[1]=0x%X\n\r",pAPDU[1]);
+    TRACE_DEBUG("pAPDU[2]=0x%X\n\r",pAPDU[2]);
+    TRACE_DEBUG("pAPDU[3]=0x%X\n\r",pAPDU[3]);
+    TRACE_DEBUG("pAPDU[4]=0x%X\n\r",pAPDU[4]);
+    TRACE_DEBUG("pAPDU[5]=0x%X\n\r",pAPDU[5]);
+    TRACE_DEBUG("wlength=%d\n\r",wLength);
+
+    ISO7816_SendChar( pAPDU[0] ); // CLA
+    ISO7816_SendChar( pAPDU[1] ); // INS
+    ISO7816_SendChar( pAPDU[2] ); // P1
+    ISO7816_SendChar( pAPDU[3] ); // P2
+    ISO7816_SendChar( pAPDU[4] ); // P3
+
+    // Handle the four structures of command APDU
+    indexApdu = 4;
+
+    if( wLength == 4 ) {
+        cmdCase = CASE1;
+        NeNc = 0;
+    }
+    else if( wLength == 5) {
+        cmdCase = CASE2;
+        NeNc = pAPDU[4]; // C5
+        if (NeNc == 0) {
+            NeNc = 256;
+        }
+    }
+    else if( wLength == 6) {
+        NeNc = pAPDU[4]; // C5
+        cmdCase = CASE3;
+    }
+    else if( wLength == 7) {
+        NeNc = pAPDU[4]; // C5
+        if( NeNc == 0 ) {
+            cmdCase = CASE2;
+            NeNc = (pAPDU[5]<<8)+pAPDU[6];
+        }
+        else {
+            cmdCase = CASE3;
+        }
+    }
+    else {
+        NeNc = pAPDU[4]; // C5
+        if( NeNc == 0 ) {
+            cmdCase = CASE3;
+            NeNc = (pAPDU[5]<<8)+pAPDU[6];
+        }
+        else {
+            cmdCase = CASE3;
+        }
+    }
+
+    TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
+
+    // Handle Procedure Bytes
+    do {
+        ISO7816_GetChar(&procByte);
+        // Handle NULL
+        if ( procByte == ISO_NULL_VAL ) {
+            TRACE_DEBUG("INS\n\r");
+            continue;
+        }
+        // Handle SW1
+        else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
+            TRACE_DEBUG("SW1\n\r");
+            SW1 = 1;
+        }
+        // Handle INS
+        else if ( pAPDU[1] == procByte) {
+            TRACE_DEBUG("HdlINS\n\r");
+            if (cmdCase == CASE2) {
+                // receive data from card
+                do {
+                    ISO7816_GetChar(&pMessage[indexMessage++]);
+                } while( 0 != --NeNc );
+            }
+            else {
+                 // Send data
+                do {
+                    ISO7816_SendChar(pAPDU[indexApdu++]);
+                } while( 0 != --NeNc );
+            }
+        }
+        // Handle INS ^ 0xff
+        else if ( pAPDU[1] == (procByte ^ 0xff)) {
+            TRACE_DEBUG("HdlINS+\n\r");
+            if (cmdCase == CASE2) {
+                // receive data from card
+                ISO7816_GetChar(&pMessage[indexMessage++]);
+            }
+            else {
+                ISO7816_SendChar(pAPDU[indexApdu++]);
+            }
+            NeNc--;
+        }
+        else {
+            // ??
+            TRACE_DEBUG("procByte=0x%X\n\r", procByte);
+            break;
+        }
+    } while (NeNc != 0);
+
+    // Status Bytes
+    if (SW1 == 0) {
+        ISO7816_GetChar(&pMessage[indexMessage++]); // SW1
+    }
+    else {
+        pMessage[indexMessage++] = procByte;
+    }
+    ISO7816_GetChar(&pMessage[indexMessage++]); // SW2
+
+    return( indexMessage );
+    
+}
+
+//------------------------------------------------------------------------------
+/// Escape ISO7816
+//------------------------------------------------------------------------------
+void ISO7816_Escape( void )
+{
+    TRACE_DEBUG("For user, if needed\n\r");
+}
+
+//------------------------------------------------------------------------------
+/// Restart clock ISO7816
+//------------------------------------------------------------------------------
+void ISO7816_RestartClock( void )
+{
+    TRACE_DEBUG("ISO7816_RestartClock\n\r");
+    AT91C_BASE_US0->US_BRGR = 13;
+}
+
+//------------------------------------------------------------------------------
+/// Stop clock ISO7816
+//------------------------------------------------------------------------------
+void ISO7816_StopClock( void )
+{
+    TRACE_DEBUG("ISO7816_StopClock\n\r");
+    AT91C_BASE_US0->US_BRGR = 0;
+}
+
+//------------------------------------------------------------------------------
+/// T0 APDU
+//------------------------------------------------------------------------------
+void ISO7816_toAPDU( void )
+{
+    TRACE_DEBUG("ISO7816_toAPDU\n\r");
+    TRACE_DEBUG("Not supported at this time\n\r");
+}
+
+//----------------------------------------------------------------------
+/// Answer To Reset (ATR)
+/// \param pAtr    ATR buffer
+/// \param pLength Pointer for store the ATR length
+//----------------------------------------------------------------------
+void ISO7816_Datablock_ATR( unsigned char* pAtr, unsigned char* pLength )
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int y;
+
+    *pLength = 0;
+
+    // Read ATR TS
+    ISO7816_GetChar(&pAtr[0]);
+    // Read ATR T0
+    ISO7816_GetChar(&pAtr[1]);
+    y = pAtr[1] & 0xF0;
+    i = 2;
+
+    // Read ATR Ti
+    while (y) {
+
+        if (y & 0x10) {  // TA[i]
+            ISO7816_GetChar(&pAtr[i++]);
+        }
+        if (y & 0x20) {  // TB[i]
+            ISO7816_GetChar(&pAtr[i++]);
+        }
+        if (y & 0x40) {  // TC[i]
+            ISO7816_GetChar(&pAtr[i++]);
+        }
+        if (y & 0x80) {  // TD[i]
+            ISO7816_GetChar(&pAtr[i]);
+            y =  pAtr[i++] & 0xF0;
+        }
+        else {
+            y = 0;
+        }
+    }
+
+    // Historical Bytes
+    y = pAtr[1] & 0x0F;
+    for( j=0; j < y; j++ ) {
+        ISO7816_GetChar(&pAtr[i++]);
+    }
+
+    TRACE_DEBUG_WP("Length = %d", i);
+    TRACE_DEBUG_WP("ATR = ");
+
+    for (j=0; j < i; j++) {
+        TRACE_DEBUG_WP("%02x ", pAtr[j]);
+    }
+
+
+    TRACE_DEBUG_WP("\n\r");
+
+    *pLength = i;
+
+}
+
+//----------------------------------------------------------------------
+/// Set data rate and clock frequency
+/// \param dwClockFrequency ICC clock frequency in KHz.
+/// \param dwDataRate       ICC data rate in bpd
+//----------------------------------------------------------------------
+void ISO7816_SetDataRateandClockFrequency( unsigned int dwClockFrequency, unsigned int dwDataRate )
+{
+    unsigned char ClockFrequency;
+
+    // Define the baud rate divisor register
+    // CD  = MCK / SCK
+    // SCK = FIDI x BAUD = 372 x 9600
+    // BOARD_MCK
+    // CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13
+    AT91C_BASE_US0->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
+
+    ClockFrequency = BOARD_MCK / AT91C_BASE_US0->US_BRGR;
+
+    AT91C_BASE_US0->US_FIDI = (ClockFrequency)/dwDataRate;
+
+}
+
+//------------------------------------------------------------------------------
+/// Pin status for ISO7816 RESET
+/// \return 1 if the Pin RstMC is high; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char ISO7816_StatusReset( void )
+{
+    return PIO_Get(&st_pinIso7816RstMC);
+}
+
+//------------------------------------------------------------------------------
+/// cold reset
+//------------------------------------------------------------------------------
+void ISO7816_cold_reset( void )
+{
+    volatile unsigned int i;
+
+    // tb: wait 400 cycles, 3.58MHz => 80�s 48000000Hz  (3840)
+    for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
+    }
+
+    AT91C_BASE_US0->US_RHR;
+    AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA | AT91C_US_RSTIT | AT91C_US_RSTNACK;
+
+    ISO7816_IccPowerOn();
+}
+
+//------------------------------------------------------------------------------
+/// Warm reset
+//------------------------------------------------------------------------------
+void ISO7816_warm_reset( void )
+{
+    volatile unsigned int i;
+
+    ISO7816_IccPowerOff();
+
+    // tb: wait 400 cycles, 3.58MHz => 80�s 48000000Hz  (3840)
+    for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
+    }
+
+    AT91C_BASE_US0->US_RHR;
+    AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA | AT91C_US_RSTIT | AT91C_US_RSTNACK;
+
+    ISO7816_IccPowerOn();
+}
+
+//----------------------------------------------------------------------
+/// Decode ATR trace
+/// \param pAtr pointer on ATR buffer
+//----------------------------------------------------------------------
+void ISO7816_Decode_ATR( unsigned char* pAtr )
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int y;
+    unsigned char offset;
+
+    TRACE_INFO_WP("ATR: Answer To Reset:\n\r");
+    TRACE_INFO_WP("TS = 0x%X Initial caracter ",pAtr[0]);
+    if( pAtr[0] == 0x3B ) {
+
+        TRACE_INFO_WP("Direct Convention\n\r");
+    }
+    else {
+        if( pAtr[0] == 0x3F ) {
+
+            TRACE_INFO_WP("Inverse Convention\n\r");
+        }
+        else {
+            TRACE_INFO_WP("BAD Convention\n\r");
+        }
+    }
+
+    TRACE_INFO_WP("T0 = 0x%X Format caracter\n\r",pAtr[1]);
+    TRACE_INFO_WP("    Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
+    TRACE_INFO_WP("    Presence further interface byte:\n\r");
+    if( pAtr[1]&0x80 ) {
+        TRACE_INFO_WP("TA ");
+    }
+    if( pAtr[1]&0x40 ) {
+        TRACE_INFO_WP("TB ");
+    }
+    if( pAtr[1]&0x20 ) {
+        TRACE_INFO_WP("TC ");
+    }
+    if( pAtr[1]&0x10 ) {
+        TRACE_INFO_WP("TD ");
+    }
+    if( pAtr[1] != 0 ) {
+        TRACE_INFO_WP(" present\n\r");
+    }
+
+    i = 2;
+    y = pAtr[1] & 0xF0;
+
+    // Read ATR Ti
+    offset = 1;
+    while (y) {
+
+        if (y & 0x10) {  // TA[i]
+            TRACE_INFO_WP("TA[%d] = 0x%X ", offset, pAtr[i]);
+            if( offset == 1 ) {
+                TRACE_INFO_WP("FI = %d ", (pAtr[i]>>8));
+                TRACE_INFO_WP("DI = %d", (pAtr[i]&0x0F));
+            }
+            TRACE_INFO_WP("\n\r");
+            i++;
+        }
+        if (y & 0x20) {  // TB[i]
+            TRACE_INFO_WP("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
+            i++;
+        }
+        if (y & 0x40) {  // TC[i]
+            TRACE_INFO_WP("TC[%d] = 0x%X ", offset, pAtr[i]);
+            if( offset == 1 ) {
+                TRACE_INFO_WP("Extra Guard Time: N = %d", pAtr[i]);
+            }
+            TRACE_INFO_WP("\n\r");
+            i++;
+        }
+        if (y & 0x80) {  // TD[i]
+            TRACE_INFO_WP("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
+            y =  pAtr[i++] & 0xF0;
+        }
+        else {
+            y = 0;
+        }
+        offset++;
+    }
+
+    // Historical Bytes
+    TRACE_INFO_WP("Historical bytes:\n\r");
+    y = pAtr[1] & 0x0F;
+    for( j=0; j < y; j++ ) {
+
+        TRACE_INFO_WP(" 0x%X", pAtr[i]);
+        if( (pAtr[i] > 0x21) && (pAtr[i] < 0x7D) ) {  // ASCII
+            TRACE_INFO_WP("(%c) ", pAtr[i]);
+        }
+        i++;
+    }
+    TRACE_INFO_WP("\n\r");
+
+}
+
+//------------------------------------------------------------------------------
+//  Initializes a ISO driver
+/// \param pPinIso7816RstMC Pin ISO 7816 Rst MC
+//------------------------------------------------------------------------------
+void ISO7816_Init( const Pin pPinIso7816RstMC )
+{
+    TRACE_DEBUG("ISO_Init\n\r");
+
+    // Pin ISO7816 initialize
+    st_pinIso7816RstMC  = pPinIso7816RstMC;
+
+    USART_Configure( AT91C_BASE_US0, 
+                     AT91C_US_USMODE_ISO7816_0
+                     | AT91C_US_CLKS_CLOCK       
+                     | AT91C_US_NBSTOP_1_BIT     
+                     | AT91C_US_PAR_EVEN         
+                     | AT91C_US_CHRL_8_BITS      
+                     | AT91C_US_CKLO             
+                     | (3<<24), // MAX_ITERATION
+                     1,
+                     0);
+
+    // Configure USART0
+    AT91C_BASE_PMC->PMC_PCER = ((unsigned int) 1 << AT91C_ID_US0);
+    // Disable interrupts
+    AT91C_BASE_US0->US_IDR = (unsigned int) -1;
+
+    AT91C_BASE_US0->US_FIDI = 372;  // by default
+    // Define the baud rate divisor register
+    // CD  = MCK / SCK
+    // SCK = FIDI x BAUD = 372 x 9600
+    // BOARD_MCK
+    // CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13
+    AT91C_BASE_US0->US_BRGR = BOARD_MCK / (372*9600);
+
+    // Write the Timeguard Register
+    AT91C_BASE_US0->US_TTGR = 5;
+
+    USART_SetTransmitterEnabled(AT91C_BASE_US0, 1);
+    USART_SetReceiverEnabled(AT91C_BASE_US0, 1);
+
+}
+
diff --git a/components/iso7816/iso7816_4.h b/components/iso7816/iso7816_4.h
new file mode 100644
index 0000000..cd46b80
--- /dev/null
+++ b/components/iso7816/iso7816_4.h
@@ -0,0 +1,87 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definition of methods for ISO7816 driver.
+/// 
+/// !Usage
+/// 
+/// -# ISO7816_Init
+/// -# ISO7816_IccPowerOff
+/// -# ISO7816_XfrBlockTPDU_T0
+/// -# ISO7816_Escape
+/// -# ISO7816_RestartClock
+/// -# ISO7816_StopClock
+/// -# ISO7816_toAPDU
+/// -# ISO7816_Datablock_ATR
+/// -# ISO7816_SetDataRateandClockFrequency
+/// -# ISO7816_StatusReset
+/// -# ISO7816_cold_reset
+/// -# ISO7816_warm_reset
+/// -# ISO7816_Decode_ATR
+//------------------------------------------------------------------------------
+
+#ifndef ISO7816_4_H
+#define ISO7816_4_H
+
+//------------------------------------------------------------------------------
+// Constants Definition
+//------------------------------------------------------------------------------
+
+/// Size max of Answer To Reset
+#define ATR_SIZE_MAX            55
+
+/// NULL byte to restart byte procedure
+#define ISO_NULL_VAL            0x60
+
+//------------------------------------------------------------------------------
+//         Exported functions
+//------------------------------------------------------------------------------
+extern void ISO7816_Init( const Pin pPinIso7816RstMC );
+extern void ISO7816_IccPowerOff(void);
+extern unsigned short ISO7816_XfrBlockTPDU_T0(const unsigned char *pAPDU, 
+                                        unsigned char *pMessage, 
+                                        unsigned short wLength );
+extern void ISO7816_Escape( void );
+extern void ISO7816_RestartClock(void);
+extern void ISO7816_StopClock( void );
+extern void ISO7816_toAPDU( void );
+extern void ISO7816_Datablock_ATR( unsigned char* pAtr, unsigned char* pLength );
+extern void ISO7816_SetDataRateandClockFrequency( unsigned int dwClockFrequency, unsigned int dwDataRate );
+extern unsigned char ISO7816_StatusReset( void );
+extern void ISO7816_cold_reset( void );
+extern void ISO7816_warm_reset( void );
+extern void ISO7816_Decode_ATR( unsigned char* pAtr );
+
+#endif // ISO7816_4_H
+
-- 
cgit v1.2.3