Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "board.h"
00047
00048
00049
00050
00051
00052 #define CASE1 1
00053 #define CASE2 2
00054 #define CASE3 3
00055
00056
00057 #define USART_SEND 0
00058 #define USART_RECEIVE 1
00059
00060 #define USART7816BAUDRATE 9600
00061
00062
00063
00064
00065 static uint8_t StateUsartGlobal = USART_RECEIVE;
00066
00067 static Pin st_pinIso7816RstMC;
00068 static Usart *UsartIso;
00069 static uint32_t UsartIsoId;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 static uint32_t ISO7816_GetChar( uint8_t *pCharToReceive )
00081 {
00082 uint32_t status;
00083 uint32_t timeout=0;
00084
00085 if( StateUsartGlobal == USART_SEND ) {
00086 while((UsartIso->US_CSR & US_CSR_TXEMPTY) == 0) {}
00087 UsartIso->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
00088 StateUsartGlobal = USART_RECEIVE;
00089 }
00090
00091
00092 while( ((UsartIso->US_CSR & US_CSR_RXRDY) == 0) ) {
00093 if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
00094 TRACE_DEBUG("TimeOut\n\r");
00095 return( 0 );
00096 }
00097 }
00098
00099 TRACE_DEBUG("T: %u\n\r", timeout);
00100
00101
00102
00103
00104
00105
00106 *pCharToReceive = ((UsartIso->US_RHR) & 0xFF);
00107
00108 status = (UsartIso->US_CSR&(US_CSR_OVRE | US_CSR_FRAME |
00109 US_CSR_PARE | US_CSR_TIMEOUT | US_CSR_NACK |
00110 (1<<10)));
00111
00112 if (status != 0 ) {
00113
00114 TRACE_DEBUG("R:0x%X\n\r", UsartIso->US_CSR);
00115 TRACE_DEBUG("Nb:0x%X\n\r", UsartIso->US_NER );
00116 UsartIso->US_CR = US_CR_RSTSTA;
00117 }
00118
00119
00120 return( status );
00121 }
00122
00123
00124
00125
00126
00127
00128 static uint32_t ISO7816_SendChar( uint8_t CharToSend )
00129 {
00130 uint32_t status;
00131
00132 if( StateUsartGlobal == USART_RECEIVE ) {
00133 UsartIso->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
00134 StateUsartGlobal = USART_SEND;
00135 }
00136
00137
00138 while((UsartIso->US_CSR & US_CSR_TXRDY) == 0) {}
00139
00140
00141
00142 UsartIso->US_THR = CharToSend;
00143
00144 status = (UsartIso->US_CSR & (US_CSR_OVRE | US_CSR_FRAME |
00145 US_CSR_PARE | US_CSR_TIMEOUT | US_CSR_NACK |
00146 (1<<10)));
00147
00148 if (status != 0 ) {
00149 TRACE_DEBUG("E:0x%X\n\r", UsartIso->US_CSR);
00150 TRACE_DEBUG("Nb:0x%X\n\r", UsartIso->US_NER );
00151 UsartIso->US_CR = US_CR_RSTSTA;
00152 }
00153
00154
00155 return( status );
00156 }
00157
00158
00159
00160
00161
00162 static void ISO7816_IccPowerOn( void )
00163 {
00164
00165 PIO_Set(&st_pinIso7816RstMC);
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175 void ISO7816_IccPowerOff( void )
00176 {
00177
00178 PIO_Clear(&st_pinIso7816RstMC);
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188 uint16_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
00189 uint8_t *pMessage,
00190 uint16_t wLength )
00191 {
00192 uint16_t NeNc;
00193 uint16_t indexApdu = 4;
00194 uint16_t indexMessage = 0;
00195 uint8_t SW1 = 0;
00196 uint8_t procByte = 0;
00197 uint8_t cmdCase;
00198 uint8_t ins;
00199
00200 TRACE_DEBUG("pAPDU[0]=0x%X\n\r",pAPDU[0]);
00201 TRACE_DEBUG("pAPDU[1]=0x%X\n\r",pAPDU[1]);
00202 TRACE_DEBUG("pAPDU[2]=0x%X\n\r",pAPDU[2]);
00203 TRACE_DEBUG("pAPDU[3]=0x%X\n\r",pAPDU[3]);
00204 TRACE_DEBUG("pAPDU[4]=0x%X\n\r",pAPDU[4]);
00205 TRACE_DEBUG("wlength=%d\n\r",wLength);
00206
00207 ISO7816_SendChar( pAPDU[0] );
00208 ISO7816_SendChar( pAPDU[1] );
00209 ISO7816_SendChar( pAPDU[2] );
00210 ISO7816_SendChar( pAPDU[3] );
00211 ISO7816_SendChar( pAPDU[4] );
00212
00213
00214 indexApdu = 4;
00215
00216 if( wLength == 4 ) {
00217 cmdCase = CASE1;
00218 NeNc = 0;
00219 } else if( wLength == 5) {
00220 cmdCase = CASE2;
00221 NeNc = pAPDU[4];
00222 if (NeNc == 0) {
00223 NeNc = 256;
00224 }
00225 } else if( wLength == 6) {
00226 NeNc = pAPDU[4];
00227 cmdCase = CASE3;
00228 } else if( wLength == 7) {
00229 NeNc = pAPDU[4];
00230 if( NeNc == 0 ) {
00231 cmdCase = CASE2;
00232 NeNc = (pAPDU[5]<<8)+pAPDU[6];
00233 } else {
00234 cmdCase = CASE3;
00235 }
00236 } else {
00237 NeNc = pAPDU[4];
00238 if( NeNc == 0 ) {
00239 cmdCase = CASE3;
00240 NeNc = (pAPDU[5]<<8)+pAPDU[6];
00241 } else {
00242 cmdCase = CASE3;
00243 }
00244 }
00245
00246 TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
00247
00248
00249 do {
00250 ISO7816_GetChar(&procByte);
00251 ins = procByte ^ 0xff;
00252
00253 if ( procByte == ISO_NULL_VAL ) {
00254 TRACE_DEBUG("INS\n\r");
00255 continue;
00256 }
00257
00258 else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
00259 TRACE_DEBUG("SW1\n\r");
00260 SW1 = 1;
00261 }
00262
00263 else if ( pAPDU[1] == procByte) {
00264 TRACE_DEBUG("HdlINS\n\r");
00265 if (cmdCase == CASE2) {
00266
00267 do {
00268 ISO7816_GetChar(&pMessage[indexMessage++]);
00269 } while( 0 != --NeNc );
00270 } else {
00271
00272 do {
00273 ISO7816_SendChar(pAPDU[indexApdu++]);
00274 } while( 0 != --NeNc );
00275 }
00276 }
00277
00278 else if ( pAPDU[1] == ins) {
00279 TRACE_DEBUG("HdlINS+\n\r");
00280 if (cmdCase == CASE2) {
00281
00282 ISO7816_GetChar(&pMessage[indexMessage++]);
00283 } else {
00284 ISO7816_SendChar(pAPDU[indexApdu++]);
00285 }
00286 NeNc--;
00287 } else {
00288
00289 TRACE_DEBUG("procByte=0x%X\n\r", procByte);
00290 break;
00291 }
00292 } while (NeNc != 0);
00293
00294
00295 if (SW1 == 0) {
00296 ISO7816_GetChar(&pMessage[indexMessage++]);
00297 } else {
00298 pMessage[indexMessage++] = procByte;
00299 }
00300 ISO7816_GetChar(&pMessage[indexMessage++]);
00301
00302 return( indexMessage );
00303
00304 }
00305
00306
00307
00308
00309 void ISO7816_Escape( void )
00310 {
00311 TRACE_DEBUG("For user, if needed\n\r");
00312 }
00313
00314
00315
00316
00317 void ISO7816_RestartClock( void )
00318 {
00319 TRACE_DEBUG("ISO7816_RestartClock\n\r");
00320 UsartIso->US_BRGR = 13;
00321 }
00322
00323
00324
00325
00326 void ISO7816_StopClock( void )
00327 {
00328 TRACE_DEBUG("ISO7816_StopClock\n\r");
00329 UsartIso->US_BRGR = 0;
00330 }
00331
00332
00333
00334
00335 void ISO7816_toAPDU( void )
00336 {
00337 TRACE_DEBUG("ISO7816_toAPDU\n\r");
00338 TRACE_DEBUG("Not supported at this time\n\r");
00339 }
00340
00341
00342
00343
00344
00345
00346 void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
00347 {
00348 uint32_t i;
00349 uint32_t j;
00350 uint32_t y;
00351
00352 *pLength = 0;
00353
00354
00355 ISO7816_GetChar(&pAtr[0]);
00356
00357 ISO7816_GetChar(&pAtr[1]);
00358 y = pAtr[1] & 0xF0;
00359 i = 2;
00360
00361
00362 while (y) {
00363 if (y & 0x10) {
00364 ISO7816_GetChar(&pAtr[i++]);
00365 }
00366 if (y & 0x20) {
00367 ISO7816_GetChar(&pAtr[i++]);
00368 }
00369 if (y & 0x40) {
00370 ISO7816_GetChar(&pAtr[i++]);
00371 }
00372 if (y & 0x80) {
00373 ISO7816_GetChar(&pAtr[i]);
00374 y = pAtr[i++] & 0xF0;
00375 } else {
00376 y = 0;
00377 }
00378 }
00379
00380
00381 y = pAtr[1] & 0x0F;
00382 for( j=0; j < y; j++ ) {
00383 ISO7816_GetChar(&pAtr[i++]);
00384 }
00385
00386 *pLength = i;
00387
00388 }
00389
00390
00391
00392
00393
00394
00395 void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency,
00396 uint32_t dwDataRate )
00397 {
00398 uint8_t ClockFrequency;
00399
00400
00401
00402
00403
00404
00405 UsartIso->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
00406
00407 ClockFrequency = BOARD_MCK / UsartIso->US_BRGR;
00408
00409 UsartIso->US_FIDI = (ClockFrequency)/dwDataRate;
00410
00411 }
00412
00413
00414
00415
00416
00417 uint8_t ISO7816_StatusReset( void )
00418 {
00419 return PIO_Get(&st_pinIso7816RstMC);
00420 }
00421
00422
00423
00424
00425 void ISO7816_cold_reset( void )
00426 {
00427 volatile uint32_t i;
00428
00429
00430 for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
00431 }
00432
00433 UsartIso->US_RHR;
00434 UsartIso->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
00435
00436 ISO7816_IccPowerOn();
00437 }
00438
00439
00440
00441
00442 void ISO7816_warm_reset( void )
00443 {
00444 volatile uint32_t i;
00445
00446 ISO7816_IccPowerOff();
00447
00448
00449 for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
00450 }
00451
00452 UsartIso->US_RHR;
00453 UsartIso->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
00454
00455 ISO7816_IccPowerOn();
00456 }
00457
00458
00459
00460
00461
00462 void ISO7816_Decode_ATR( uint8_t* pAtr )
00463 {
00464 uint32_t i;
00465 uint32_t j;
00466 uint32_t y;
00467 uint8_t offset;
00468
00469 printf("\n\r");
00470 printf("ATR: Answer To Reset:\n\r");
00471 printf("TS = 0x%X Initial character ",pAtr[0]);
00472 if( pAtr[0] == 0x3B ) {
00473
00474 printf("Direct Convention\n\r");
00475 } else {
00476 if( pAtr[0] == 0x3F ) {
00477 printf("Inverse Convention\n\r");
00478 } else {
00479 printf("BAD Convention\n\r");
00480 }
00481 }
00482
00483 printf("T0 = 0x%X Format character\n\r",pAtr[1]);
00484 printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
00485 printf(" Presence further interface byte:\n\r");
00486 if( pAtr[1]&0x10 ) {
00487 printf("TA ");
00488 }
00489 if( pAtr[1]&0x20 ) {
00490 printf("TB ");
00491 }
00492 if( pAtr[1]&0x40 ) {
00493 printf("TC ");
00494 }
00495 if( pAtr[1]&0x80 ) {
00496 printf("TD ");
00497 }
00498 if( pAtr[1] != 0 ) {
00499 printf(" present\n\r");
00500 }
00501
00502 i = 2;
00503 y = pAtr[1] & 0xF0;
00504
00505
00506 offset = 1;
00507 while (y) {
00508
00509 if (y & 0x10) {
00510 printf("TA[%d] = 0x%X ", offset, pAtr[i]);
00511 if( offset == 1 ) {
00512 printf("FI = %d ", (pAtr[i]>>4));
00513 printf("DI = %d", (pAtr[i]&0x0F));
00514 }
00515 printf("\n\r");
00516 i++;
00517 }
00518 if (y & 0x20) {
00519 printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
00520 i++;
00521 }
00522 if (y & 0x40) {
00523 printf("TC[%d] = 0x%X ", offset, pAtr[i]);
00524 if( offset == 1 ) {
00525 printf("Extra Guard Time: N = %d", pAtr[i]);
00526 }
00527 printf("\n\r");
00528 i++;
00529 }
00530 if (y & 0x80) {
00531 printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
00532 y = pAtr[i++] & 0xF0;
00533 } else {
00534 y = 0;
00535 }
00536 offset++;
00537 }
00538
00539
00540 printf("Historical bytes:\n\r");
00541 y = pAtr[1] & 0x0F;
00542 for( j=0; j < y; j++ ) {
00543 printf(" 0x%X", pAtr[i]);
00544 if( (pAtr[i] > 0x21) && (pAtr[i] < 0x7D) ) {
00545 printf("(%c) ", pAtr[i]);
00546 }
00547 i++;
00548 }
00549 printf("\n\r\n\r");
00550
00551 }
00552
00553
00554
00555
00556
00557
00558 void ISO7816_Init( Usart *pUsart, uint32_t usartId , const Pin pPinIso7816RstMC )
00559 {
00560 TRACE_DEBUG("ISO_Init\n\r");
00561 UsartIso = pUsart;
00562 UsartIsoId = usartId;
00563 uint32_t baudrate = USART7816BAUDRATE;
00564
00565
00566 st_pinIso7816RstMC = pPinIso7816RstMC;
00567
00568 PMC_EnablePeripheral(UsartIsoId);
00569
00570 UsartIso->US_FIDI = 372;
00571
00572
00573 USART_Configure( UsartIso,
00574 US_MR_USART_MODE_IS07816_T_0
00575 | US_MR_USCLKS_MCK
00576 | US_MR_NBSTOP_1_BIT
00577 | US_MR_PAR_EVEN
00578 | US_MR_CHRL_8_BIT
00579 | US_MR_CLKO
00580 | (3<<24),
00581 baudrate,
00582 BOARD_MCK);
00583
00584
00585 UsartIso->US_TTGR = 5;
00586 }
00587