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