blob: 4666d77e18411ebc5df85703a7d741385b5bb3ed [file] [log] [blame]
Christina Quast32a90ac2015-03-10 16:18:16 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2009, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/**
31 * \file
32 *
33 * \section Purpose
34 *
35 * ISO 7816 driver
36 *
37 * \section Usage
38 *
39 * Explanation on the usage of the code made available through the header file.
40 */
41
42/*------------------------------------------------------------------------------
43 * Headers
44 *------------------------------------------------------------------------------*/
45
46#include "board.h"
47
48/*------------------------------------------------------------------------------
49 * Definitions
50 *------------------------------------------------------------------------------*/
51/** Case for APDU commands*/
52#define CASE1 1
53#define CASE2 2
54#define CASE3 3
55
56/** Flip flop for send and receive char */
57#define USART_SEND 0
58#define USART_RCV 1
59
60#if !defined(BOARD_ISO7816_BASE_USART)
61 #define BOARD_ISO7816_BASE_USART USART1
62 #define BOARD_ISO7816_ID_USART ID_USART1
63#endif
64
65/*-----------------------------------------------------------------------------
66 * Internal variables
67 *-----------------------------------------------------------------------------*/
68/** Variable for state of send and receive froom USART */
69static uint8_t StateUsartGlobal = USART_RCV;
70/** Pin reset master card */
Christina Quast2fcef412015-03-10 15:51:21 +010071static Pin *st_pinIso7816RstMC;
Christina Quast32a90ac2015-03-10 16:18:16 +010072
73/*----------------------------------------------------------------------------
74 * Internal functions
75 *----------------------------------------------------------------------------*/
76
77/**
78 * Get a character from ISO7816
79 * \param pCharToReceive Pointer for store the received char
80 * \return 0: if timeout else status of US_CSR
81 */
82static uint32_t ISO7816_GetChar( uint8_t *pCharToReceive )
83{
84 uint32_t status;
85 uint32_t timeout=0;
86
87 if( StateUsartGlobal == USART_SEND ) {
88 while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXEMPTY) == 0) {}
89 BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
90 StateUsartGlobal = USART_RCV;
91 }
92
93 /* Wait USART ready for reception */
94 while( ((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_RXRDY) == 0) ) {
95 if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
96 TRACE_WARNING("TimeOut\n\r");
97 return( 0 );
98 }
99 }
100
101 /* At least one complete character has been received and US_RHR has not yet been read. */
102
103 /* Get a char */
104 *pCharToReceive = ((BOARD_ISO7816_BASE_USART->US_RHR) & 0xFF);
105
106 status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
107 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
108 (1<<10)));
109
110 if (status != 0 ) {
111 TRACE_DEBUG("R:0x%" PRIX32 "\n\r", status);
112 TRACE_DEBUG("R:0x%" PRIX32 "\n\r", BOARD_ISO7816_BASE_USART->US_CSR);
113 TRACE_DEBUG("Nb:0x%" PRIX32 "\n\r", BOARD_ISO7816_BASE_USART->US_NER );
114 BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;
115 }
116
117 /* Return status */
118 return( status );
119}
120
121
122/**
123 * Send a char to ISO7816
124 * \param CharToSend char to be send
125 * \return status of US_CSR
126 */
127static uint32_t ISO7816_SendChar( uint8_t CharToSend )
128{
129 uint32_t status;
130
131 TRACE_DEBUG("********** Send char: %c (0x%X)\n\r", CharToSend, CharToSend);
132
133 if( StateUsartGlobal == USART_RCV ) {
134 BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
135 StateUsartGlobal = USART_SEND;
136 }
137
138 /* Wait USART ready for transmit */
139 while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXRDY) == 0) {}
140 /* There is no character in the US_THR */
141
142 /* Transmit a char */
143 BOARD_ISO7816_BASE_USART->US_THR = CharToSend;
144
145 status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
146 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
147 (1<<10)));
148
149 if (status != 0 ) {
150 TRACE_DEBUG("******* status: 0x%" PRIX32 " (Overrun: %" PRIX32 ", NACK: %" PRIX32 ", Timeout: %" PRIX32 ", underrun: %" PRIX32 ")\n\r",
151 status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
152 ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
153
154 TRACE_DEBUG("E (USART CSR reg):0x%" PRIX32 "\n\r", BOARD_ISO7816_BASE_USART->US_CSR);
155 TRACE_DEBUG("Nb (Number of errors):0x%" PRIX32 "\n\r", BOARD_ISO7816_BASE_USART->US_NER );
156 BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;
157 }
158
159 /* Return status */
160 return( status );
161}
162
163
164/**
165 * Iso 7816 ICC power on
166 */
167static void ISO7816_IccPowerOn( void )
168{
169 /* Set RESET Master Card */
Christina Quast2fcef412015-03-10 15:51:21 +0100170 PIO_Set(st_pinIso7816RstMC);
Christina Quast32a90ac2015-03-10 16:18:16 +0100171}
172
173/*----------------------------------------------------------------------------
174 * Exported functions
175 *----------------------------------------------------------------------------*/
176
177/**
178 * Iso 7816 ICC power off
179 */
180void ISO7816_IccPowerOff( void )
181{
182 /* Clear RESET Master Card */
Christina Quast2fcef412015-03-10 15:51:21 +0100183 PIO_Clear(st_pinIso7816RstMC);
Christina Quast32a90ac2015-03-10 16:18:16 +0100184}
185
186/**
Christina Quast73c2b642015-04-07 13:49:26 +0200187 * Transfert Block TPDU T=0
188 * \param pAPDU APDU buffer
189 * \param pMessage Message buffer
190 * \param wLength Block length
191 * \param indexMsg Message index
192 * \return 0 on success, content of US_CSR otherwise
Christina Quast32a90ac2015-03-10 16:18:16 +0100193 */
Christina Quast73c2b642015-04-07 13:49:26 +0200194uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
Christina Quast32a90ac2015-03-10 16:18:16 +0100195 uint8_t *pMessage,
Christina Quast73c2b642015-04-07 13:49:26 +0200196 uint16_t wLength,
197 uint16_t *retlen )
Christina Quast32a90ac2015-03-10 16:18:16 +0100198{
199 uint16_t NeNc;
200 uint16_t indexApdu = 4;
Christina Quast73c2b642015-04-07 13:49:26 +0200201 uint16_t indexMsg = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100202 uint8_t SW1 = 0;
203 uint8_t procByte;
204 uint8_t cmdCase;
Christina Quast73c2b642015-04-07 13:49:26 +0200205 uint32_t status = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100206
Christina Quastc63df592015-03-10 23:32:45 +0100207 TRACE_INFO("pAPDU[0]=0x%X\n\r",pAPDU[0]);
208 TRACE_INFO("pAPDU[1]=0x%X\n\r",pAPDU[1]);
209 TRACE_INFO("pAPDU[2]=0x%X\n\r",pAPDU[2]);
210 TRACE_INFO("pAPDU[3]=0x%X\n\r",pAPDU[3]);
211 TRACE_INFO("pAPDU[4]=0x%X\n\r",pAPDU[4]);
212 TRACE_INFO("pAPDU[5]=0x%X\n\r",pAPDU[5]);
213 TRACE_INFO("wlength=%d\n\r",wLength);
Christina Quast32a90ac2015-03-10 16:18:16 +0100214
215 ISO7816_SendChar( pAPDU[0] ); /* CLA */
216 ISO7816_SendChar( pAPDU[1] ); /* INS */
217 ISO7816_SendChar( pAPDU[2] ); /* P1 */
218 ISO7816_SendChar( pAPDU[3] ); /* P2 */
219 ISO7816_SendChar( pAPDU[4] ); /* P3 */
220
221 /* Handle the four structures of command APDU */
Christina Quastc63df592015-03-10 23:32:45 +0100222 indexApdu = 5;
Christina Quast32a90ac2015-03-10 16:18:16 +0100223
224 if( wLength == 4 ) {
225 cmdCase = CASE1;
226 NeNc = 0;
227 }
228 else if( wLength == 5) {
229 cmdCase = CASE2;
230 NeNc = pAPDU[4]; /* C5 */
231 if (NeNc == 0) {
232 NeNc = 256;
233 }
234 }
235 else if( wLength == 6) {
236 NeNc = pAPDU[4]; /* C5 */
237 cmdCase = CASE3;
238 }
239 else if( wLength == 7) {
240 NeNc = pAPDU[4]; /* C5 */
241 if( NeNc == 0 ) {
242 cmdCase = CASE2;
243 NeNc = (pAPDU[5]<<8)+pAPDU[6];
244 }
245 else {
246 cmdCase = CASE3;
247 }
248 }
249 else {
250 NeNc = pAPDU[4]; /* C5 */
251 if( NeNc == 0 ) {
252 cmdCase = CASE3;
253 NeNc = (pAPDU[5]<<8)+pAPDU[6];
254 }
255 else {
256 cmdCase = CASE3;
257 }
258 }
259
260 TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
261
262 /* Handle Procedure Bytes */
263 do {
Christina Quast73c2b642015-04-07 13:49:26 +0200264 status = ISO7816_GetChar(&procByte);
265 if (status != 0) {
266 return status;
267 }
Christina Quast2fcef412015-03-10 15:51:21 +0100268 TRACE_INFO("procByte: 0x%X\n\r", procByte);
Christina Quast32a90ac2015-03-10 16:18:16 +0100269 /* Handle NULL */
270 if ( procByte == ISO_NULL_VAL ) {
Christina Quast2fcef412015-03-10 15:51:21 +0100271 TRACE_INFO("INS\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100272 continue;
273 }
274 /* Handle SW1 */
275 else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
Christina Quast2fcef412015-03-10 15:51:21 +0100276 TRACE_INFO("SW1\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100277 SW1 = 1;
278 }
279 /* Handle INS */
280 else if ( pAPDU[1] == procByte) {
Christina Quast2fcef412015-03-10 15:51:21 +0100281 TRACE_INFO("HdlINS\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100282 if (cmdCase == CASE2) {
283 /* receive data from card */
284 do {
Christina Quast73c2b642015-04-07 13:49:26 +0200285 status = ISO7816_GetChar(&pMessage[indexMsg++]);
286 } while(( 0 != --NeNc) && (status == 0) );
287 if (status != 0) {
288 return status;
289 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100290 }
291 else {
292 /* Send data */
293 do {
Christina Quastc63df592015-03-10 23:32:45 +0100294 TRACE_INFO("Send %X", pAPDU[indexApdu]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100295 ISO7816_SendChar(pAPDU[indexApdu++]);
296 } while( 0 != --NeNc );
297 }
298 }
299 /* Handle INS ^ 0xff */
Christina Quast767fdeb2015-04-07 13:50:20 +0200300 else
301 #pragma GCC diagnostic push
302 #pragma GCC diagnostic ignored "-Wsign-compare"
303 if ( pAPDU[1] == (procByte ^ 0xff)) {
304 #pragma GCC diagnostic pop
Christina Quast2fcef412015-03-10 15:51:21 +0100305 TRACE_INFO("HdlINS+\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100306 if (cmdCase == CASE2) {
307 /* receive data from card */
Christina Quast73c2b642015-04-07 13:49:26 +0200308 status = ISO7816_GetChar(&pMessage[indexMsg++]);
309 if (status != 0) {
310 return status;
311 }
312 TRACE_INFO("Rcv: 0x%X\n\r", pMessage[indexMsg-1]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100313 }
314 else {
Christina Quast73c2b642015-04-07 13:49:26 +0200315 status = ISO7816_SendChar(pAPDU[indexApdu++]);
316 if (status != 0) {
317 return status;
318 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100319 }
320 NeNc--;
321 }
322 else {
323 /* ?? */
Christina Quast2fcef412015-03-10 15:51:21 +0100324 TRACE_INFO("procByte=0x%X\n\r", procByte);
Christina Quast32a90ac2015-03-10 16:18:16 +0100325 break;
326 }
327 } while (NeNc != 0);
328
329 /* Status Bytes */
330 if (SW1 == 0) {
Christina Quast73c2b642015-04-07 13:49:26 +0200331 status = ISO7816_GetChar(&pMessage[indexMsg++]); /* SW1 */
332 if (status != 0) {
333 return status;
334 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100335 }
336 else {
Christina Quast73c2b642015-04-07 13:49:26 +0200337 pMessage[indexMsg++] = procByte;
Christina Quast32a90ac2015-03-10 16:18:16 +0100338 }
Christina Quast73c2b642015-04-07 13:49:26 +0200339 status = ISO7816_GetChar(&pMessage[indexMsg++]); /* SW2 */
340 if (status != 0) {
341 return status;
342 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100343
Christina Quast73c2b642015-04-07 13:49:26 +0200344 TRACE_WARNING("SW1=0x%X, SW2=0x%X\n\r", pMessage[indexMsg-2], pMessage[indexMsg-1]);
Christina Quast2fcef412015-03-10 15:51:21 +0100345
Christina Quast73c2b642015-04-07 13:49:26 +0200346 *retlen = indexMsg;
347 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100348
349}
350
351/**
352 * Escape ISO7816
353 */
354void ISO7816_Escape( void )
355{
356 TRACE_DEBUG("For user, if needed\n\r");
357}
358
359/**
360 * Restart clock ISO7816
361 */
362void ISO7816_RestartClock( void )
363{
364 TRACE_DEBUG("ISO7816_RestartClock\n\r");
365 BOARD_ISO7816_BASE_USART->US_BRGR = 13;
366}
367
368/**
369 * Stop clock ISO7816
370 */
371void ISO7816_StopClock( void )
372{
373 TRACE_DEBUG("ISO7816_StopClock\n\r");
374 BOARD_ISO7816_BASE_USART->US_BRGR = 0;
375}
376
377/**
378 * T0 APDU
379 */
380void ISO7816_toAPDU( void )
381{
382 TRACE_DEBUG("ISO7816_toAPDU\n\r");
383 TRACE_DEBUG("Not supported at this time\n\r");
384}
385
386/**
387 * Answer To Reset (ATR)
388 * \param pAtr ATR buffer
389 * \param pLength Pointer for store the ATR length
390 * \return 0: if timeout else status of US_CSR
391 */
392uint32_t ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
393{
394 uint32_t i;
395 uint32_t j;
396 uint32_t y;
397 uint32_t status = 0;
398
399 *pLength = 0;
400
401 /* Read ATR TS */
402 // FIXME: There should always be a check for the GetChar return value..0 means timeout
403 status = ISO7816_GetChar(&pAtr[0]);
Christina Quast73c2b642015-04-07 13:49:26 +0200404 if (status != 0) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100405 return status;
Christina Quast73c2b642015-04-07 13:49:26 +0200406 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100407
408 /* Read ATR T0 */
Christina Quast73c2b642015-04-07 13:49:26 +0200409 status = ISO7816_GetChar(&pAtr[1]);
410 if (status != 0) {
411 return status;
412 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100413 y = pAtr[1] & 0xF0;
414 i = 2;
415
416 /* Read ATR Ti */
Christina Quast73c2b642015-04-07 13:49:26 +0200417 while (y && (status == 0)) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100418
419 if (y & 0x10) { /* TA[i] */
Christina Quast73c2b642015-04-07 13:49:26 +0200420 status = ISO7816_GetChar(&pAtr[i++]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100421 }
422 if (y & 0x20) { /* TB[i] */
Christina Quast73c2b642015-04-07 13:49:26 +0200423 status = ISO7816_GetChar(&pAtr[i++]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100424 }
425 if (y & 0x40) { /* TC[i] */
Christina Quast73c2b642015-04-07 13:49:26 +0200426 status = ISO7816_GetChar(&pAtr[i++]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100427 }
428 if (y & 0x80) { /* TD[i] */
Christina Quast73c2b642015-04-07 13:49:26 +0200429 status = ISO7816_GetChar(&pAtr[i]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100430 y = pAtr[i++] & 0xF0;
431 }
432 else {
433 y = 0;
434 }
435 }
Christina Quast73c2b642015-04-07 13:49:26 +0200436 if (status != 0) {
437 return status;
438 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100439
440 /* Historical Bytes */
441 y = pAtr[1] & 0x0F;
Christina Quast73c2b642015-04-07 13:49:26 +0200442 for( j=0; (j < y) && (status == 0); j++ ) {
443 status = ISO7816_GetChar(&pAtr[i++]);
444 }
445
446 if (status != 0) {
447 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100448 }
449
450 *pLength = i;
Christina Quast73c2b642015-04-07 13:49:26 +0200451 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100452}
453
454/**
455 * Set data rate and clock frequency
456 * \param dwClockFrequency ICC clock frequency in KHz.
457 * \param dwDataRate ICC data rate in bpd
458 */
459void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate )
460{
461 uint8_t ClockFrequency;
462
463 /* Define the baud rate divisor register */
464 /* CD = MCK / SCK */
465 /* SCK = FIDI x BAUD = 372 x 9600 */
466 /* BOARD_MCK */
467 /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
468 BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
469
470 ClockFrequency = BOARD_MCK / BOARD_ISO7816_BASE_USART->US_BRGR;
471
472 BOARD_ISO7816_BASE_USART->US_FIDI = (ClockFrequency)/dwDataRate;
473
474}
475
476/**
477 * Pin status for ISO7816 RESET
478 * \return 1 if the Pin RstMC is high; otherwise 0.
479 */
480uint8_t ISO7816_StatusReset( void )
481{
Christina Quast2fcef412015-03-10 15:51:21 +0100482 return PIO_Get(st_pinIso7816RstMC);
Christina Quast32a90ac2015-03-10 16:18:16 +0100483}
484
485/**
486 * cold reset
487 */
488void ISO7816_cold_reset( void )
489{
490 volatile uint32_t i;
491
492 /* tb: wait 400 cycles*/
493 for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
494 }
495
496 BOARD_ISO7816_BASE_USART->US_RHR;
497 BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
498
499 ISO7816_IccPowerOn();
500}
501
502/**
503 * Warm reset
504 */
505void ISO7816_warm_reset( void )
506{
507 volatile uint32_t i;
508
509// Clears Reset
510 ISO7816_IccPowerOff();
511
512 /* tb: wait 400 cycles */
513 for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
514 }
515
516 BOARD_ISO7816_BASE_USART->US_RHR;
517 BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
518
519// Sets Reset
520 ISO7816_IccPowerOn();
521}
522
523/**
524 * Decode ATR trace
525 * \param pAtr pointer on ATR buffer
526 */
527void ISO7816_Decode_ATR( uint8_t* pAtr )
528{
529 uint32_t i;
530 uint32_t j;
531 uint32_t y;
532 uint8_t offset;
533
534 printf("\n\r");
535 printf("ATR: Answer To Reset:\n\r");
536 printf("TS = 0x%X Initial character ",pAtr[0]);
537 if( pAtr[0] == 0x3B ) {
538
539 printf("Direct Convention\n\r");
540 }
541 else {
542 if( pAtr[0] == 0x3F ) {
543
544 printf("Inverse Convention\n\r");
545 }
546 else {
547 printf("BAD Convention\n\r");
548 }
549 }
550
551 printf("T0 = 0x%X Format caracter\n\r",pAtr[1]);
552 printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
553 printf(" Presence further interface byte:\n\r");
554 if( pAtr[1]&0x80 ) {
555 printf("TA ");
556 }
557 if( pAtr[1]&0x40 ) {
558 printf("TB ");
559 }
560 if( pAtr[1]&0x20 ) {
561 printf("TC ");
562 }
563 if( pAtr[1]&0x10 ) {
564 printf("TD ");
565 }
566 if( pAtr[1] != 0 ) {
567 printf(" present\n\r");
568 }
569
570 i = 2;
571 y = pAtr[1] & 0xF0;
572
573 /* Read ATR Ti */
574 offset = 1;
575 while (y) {
576
577 if (y & 0x10) { /* TA[i] */
578 printf("TA[%d] = 0x%X ", offset, pAtr[i]);
579 if( offset == 1 ) {
580 printf("FI = %d ", (pAtr[i]>>8));
581 printf("DI = %d", (pAtr[i]&0x0F));
582 }
583 printf("\n\r");
584 i++;
585 }
586 if (y & 0x20) { /* TB[i] */
587 printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
588 i++;
589 }
590 if (y & 0x40) { /* TC[i] */
591 printf("TC[%d] = 0x%X ", offset, pAtr[i]);
592 if( offset == 1 ) {
593 printf("Extra Guard Time: N = %d", pAtr[i]);
594 }
595 printf("\n\r");
596 i++;
597 }
598 if (y & 0x80) { /* TD[i] */
599 printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
600 y = pAtr[i++] & 0xF0;
601 }
602 else {
603 y = 0;
604 }
605 offset++;
606 }
607
608 /* Historical Bytes */
609 printf("Historical bytes:\n\r");
610 y = pAtr[1] & 0x0F;
611 for( j=0; j < y; j++ ) {
612 printf(" 0x%X", pAtr[i]);
613 i++;
614 }
615 printf("\n\r\n\r");
616
617}
618
619/** Initializes a ISO driver
620 * \param pPinIso7816RstMC Pin ISO 7816 Rst MC
621 */
Christina Quast2fcef412015-03-10 15:51:21 +0100622void ISO7816_Init( const Pin *pPinIso7816RstMC )
Christina Quast32a90ac2015-03-10 16:18:16 +0100623{
624 TRACE_DEBUG("ISO_Init\n\r");
625
626 /* Pin ISO7816 initialize */
Christina Quastca005692015-04-06 23:26:14 +0200627 st_pinIso7816RstMC = (Pin *)pPinIso7816RstMC;
Christina Quast32a90ac2015-03-10 16:18:16 +0100628
629 USART_Configure( BOARD_ISO7816_BASE_USART,
630 US_MR_USART_MODE_IS07816_T_0
631 | US_MR_USCLKS_MCK
632 | US_MR_NBSTOP_1_BIT
633 | US_MR_PAR_EVEN
634 | US_MR_CHRL_8_BIT
635 | US_MR_CLKO
636 | (3<<24), /* MAX_ITERATION */
637 1,
638 0);
639
640 /* Configure USART */
641 PMC_EnablePeripheral(BOARD_ISO7816_ID_USART);
642 /* Disable interrupts */
643 BOARD_ISO7816_BASE_USART->US_IDR = (uint32_t) -1;
644
645 BOARD_ISO7816_BASE_USART->US_FIDI = 372; /* by default */
646 /* Define the baud rate divisor register */
647 /* CD = MCK / SCK */
648 /* SCK = FIDI x BAUD = 372 x 9600 */
649 /* BOARD_MCK */
650 /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
651 BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (372*9600);
652
653 /* Write the Timeguard Register */
654 BOARD_ISO7816_BASE_USART->US_TTGR = 5;
655
656 USART_SetTransmitterEnabled(BOARD_ISO7816_BASE_USART, 1);
657 USART_SetReceiverEnabled(BOARD_ISO7816_BASE_USART, 1);
658
659}
660