00001
00028 #define F_CPU 16000000UL // Change this to the correct frequency
00029
00030
00031 #ifndef __DELAY_BACKWARD_COMPATIBLE__
00032 #define __DELAY_BACKWARD_COMPATIBLE__
00033 #endif
00034
00035 #include <avr/io.h>
00036 #include <avr/interrupt.h>
00037 #include <avr/sleep.h>
00038 #include <avr/power.h>
00039 #include <avr/eeprom.h>
00040 #include <string.h>
00041 #include <util/delay.h>
00042 #include <stdlib.h>
00043 #include <avr/wdt.h>
00044
00045 #include "emv.h"
00046 #include "scd_hal.h"
00047 #include "scd_io.h"
00048 #include "scd.h"
00049 #include "utils.h"
00050 #include "terminal.h"
00051 #include "emv_values.h"
00052 #include "scd_values.h"
00053
00055 #define LCD_ENABLED 1
00056
00058 #define DEBUG 0
00059
00061 #define ICC_PRES_INT_ENABLE 1
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #if LCD_ENABLED
00074 static char* strATRSent = "ATR Sent";
00075 static char* strDone = "All Done";
00076 static char* strError = "Error Ocurred";
00077 static char* strDataSent = "Data Sent";
00078 static char* strScroll = "BC to scroll";
00079 static char* strSelect = "BD to select";
00080 static char* strAvailable = "Avail. apps:";
00081 static char* strDecide = "BA = yesBD = no";
00082 static char* strCardInserted = "Card inserted";
00083 static char* strBadProtocol = "Only T=0support";
00084 static char* strPINOK = "PIN OK";
00085 static char* strPINBAD = "PIN BAD";
00086 static char* strPINTryExceeded = "PIN try exceeded";
00087 static char* strPowerUp = "Power Up";
00088 static char* strPowerDown = "Power Down";
00089 #endif
00090
00091
00092 uint8_t warmResetByte;
00093 CRP* transactionData[MAX_EXCHANGES];
00094 uint8_t nTransactions;
00095 uint8_t lcdAvailable;
00096 uint8_t nCounter;
00097 uint8_t selected;
00098
00099
00100
00101 FILE lcd_str = FDEV_SETUP_STREAM(LcdPutchar, NULL, _FDEV_SETUP_WRITE);
00102
00103
00107 int main(void)
00108 {
00109 uint8_t sreg;
00110
00111
00112 InitSCD();
00113
00114
00115
00116
00117
00118 if(GetButtonB() == 0)
00119 {
00120 selected = SelectApplication();
00121
00122 if(selected == APP_ERASE_EEPROM)
00123 {
00124 Led2On();
00125 EraseEEPROM();
00126 Led2Off();
00127 wdt_enable(WDTO_15MS);
00128 }
00129 else
00130 {
00131 sreg = SREG;
00132 cli();
00133 eeprom_write_byte((uint8_t*)EEPROM_APPLICATION, selected);
00134 SREG = sreg;
00135 }
00136
00137
00138 wdt_enable(WDTO_15MS);
00139 }
00140 else
00141 {
00142 sreg = SREG;
00143 cli();
00144 selected = eeprom_read_byte((uint8_t*)EEPROM_APPLICATION);
00145 SREG = sreg;
00146 }
00147
00148
00149 switch(selected)
00150 {
00151 case APP_STORE_PIN:
00152 StorePIN();
00153 break;
00154
00155 case APP_LOG_FORWARD:
00156 ForwardData();
00157 break;
00158
00159 case APP_FW_MODIFY_PIN:
00160 ForwardAndChangePIN();
00161 break;
00162
00163 case APP_FILTER_GENERATEAC:
00164 FilterGenerateAC();
00165 break;
00166
00167 case APP_FILTER_LOG:
00168 FilterAndLog();
00169 break;
00170
00171 case APP_TERMINAL_1:
00172 Terminal1();
00173 break;
00174
00175 default:
00176 selected = APP_TERMINAL_1;
00177 eeprom_write_byte((uint8_t*)EEPROM_APPLICATION, selected);
00178 Terminal1();
00179 }
00180
00181
00182
00183
00184 SwitchLeds();
00185 }
00186
00200 uint8_t SelectApplication()
00201 {
00202 volatile uint8_t tmp;
00203 uint8_t i;
00204
00205 if(!lcdAvailable) return 0;
00206
00207 InitLCD();
00208 fprintf(stderr, "\n");
00209
00210 while(1){
00211 fprintf(stderr, "%s\n", strScroll);
00212 do{
00213 tmp = GetButton();
00214 }while((tmp & BUTTON_C) == 0);
00215 _delay_ms(500);
00216
00217 fprintf(stderr, "%s\n", strSelect);
00218 do{
00219 tmp = GetButton();
00220 }while((tmp & BUTTON_C) == 0);
00221 _delay_ms(500);
00222
00223 fprintf(stderr, "%s\n", strAvailable);
00224 do{
00225 tmp = GetButton();
00226 }while((tmp & BUTTON_C) == 0);
00227 _delay_ms(500);
00228
00229 for(i = 0; i < APPLICATION_COUNT; i++)
00230 {
00231 fprintf(stderr, "%s\n", appStrings[i]);
00232 while(1)
00233 {
00234 tmp = GetButton();
00235 if((tmp & BUTTON_D) != 0) return (i + 1);
00236 if((tmp & BUTTON_C) != 0) break;
00237 }
00238 _delay_ms(500);
00239 }
00240 }
00241
00242 return 0;
00243 }
00244
00245
00249 uint8_t TestDDA(uint8_t convention, uint8_t TC1)
00250 {
00251 uint8_t status = 0;
00252 RAPDU *response = NULL;
00253 FCITemplate *fci = NULL;
00254 APPINFO *appInfo = NULL;
00255 RECORD *tData = NULL;
00256 ByteArray *offlineAuthData = NULL;
00257 ByteArray *ddata = NULL;
00258
00259 wdt_reset();
00260
00261
00262
00263 fci = SelectFromAID(convention, TC1);
00264 if(fci == NULL)
00265 {
00266 fprintf(stderr, "%s\n", strError);
00267 status = 1;
00268 goto endtransaction;
00269 }
00270 wdt_reset();
00271
00272
00273 appInfo = InitializeTransaction(convention, TC1, fci);
00274 if(appInfo == NULL)
00275 {
00276 fprintf(stderr, "%s\n", strError);
00277 status = 1;
00278 goto endfci;
00279 }
00280 wdt_reset();
00281
00282
00283 offlineAuthData = (ByteArray*)malloc(sizeof(ByteArray));
00284 tData = GetTransactionData(convention, TC1, appInfo, offlineAuthData);
00285 if(tData == NULL)
00286 {
00287 fprintf(stderr, "%s\n", strError);
00288 status = 1;
00289 goto endappinfo;
00290 }
00291 wdt_reset();
00292
00293
00294 ddata = MakeByteArrayV(4,
00295 0x05, 0x06, 0x07, 0x08
00296 );
00297 response = SignDynamicData(convention, TC1, ddata);
00298 if(response == NULL)
00299 {
00300 fprintf(stderr, "%s\n", strError);
00301 status = 1;
00302 goto endtdata;
00303 }
00304 FreeRAPDU(response);
00305
00306 endddata:
00307 FreeByteArray(ddata);
00308 endtdata:
00309 FreeRECORD(tData);
00310 endappinfo:
00311 FreeAPPINFO(appInfo);
00312 if(offlineAuthData != NULL)
00313 FreeByteArray(offlineAuthData);
00314 endfci:
00315 FreeFCITemplate(fci);
00316 endtransaction:
00317 DeactivateICC();
00318 asm volatile("nop\n\t"::);
00319 _delay_ms(50);
00320
00321 return status;
00322 }
00323
00324
00332 uint8_t Terminal1()
00333 {
00334 uint8_t convention, proto, TC1, TA3, TB3;
00335 uint8_t tmp;
00336 RAPDU *response = NULL;
00337 FCITemplate *fci = NULL;
00338 APPINFO *appInfo = NULL;
00339 RECORD *tData = NULL;
00340 ByteArray *offlineAuthData = NULL;
00341 ByteArray *pinTryCounter = NULL;
00342 ByteArray *pin = NULL;
00343 ByteArray *ddata = NULL;
00344 GENERATE_AC_PARAMS acParams;
00345 const TLV *cdol = NULL;
00346
00347
00348 SleepUntilCardInserted();
00349
00350
00351 if(!IsICCInserted())
00352 {
00353 wdt_enable(WDTO_15MS);
00354 _delay_ms(100);
00355 }
00356
00357 if(lcdAvailable)
00358 {
00359 InitLCD();
00360 fprintf(stderr, "\n");
00361 fprintf(stderr, "%s\n", strCardInserted);
00362 _delay_ms(1000);
00363 }
00364 else
00365 return RET_ERROR;
00366
00367
00368 wdt_enable(WDTO_4S);
00369
00370
00371 if(ResetICC(0, &convention, &proto, &TC1, &TA3, &TB3)) return RET_ERROR;
00372 if(proto != 0)
00373 {
00374 fprintf(stderr, "%s\n", strBadProtocol);
00375 return RET_ERROR;
00376 }
00377 wdt_reset();
00378
00379
00380
00381 fci = SelectFromAID(convention, TC1);
00382 if(fci == NULL)
00383 {
00384 fprintf(stderr, "%s\n", strError);
00385 goto endtransaction;
00386 }
00387 wdt_reset();
00388
00389
00390 appInfo = InitializeTransaction(convention, TC1, fci);
00391 if(appInfo == NULL)
00392 {
00393 fprintf(stderr, "%s\n", strError);
00394 goto endfci;
00395 }
00396 wdt_reset();
00397
00398
00399 offlineAuthData = (ByteArray*)malloc(sizeof(ByteArray));
00400 tData = GetTransactionData(convention, TC1, appInfo, offlineAuthData);
00401 if(tData == NULL)
00402 {
00403 fprintf(stderr, "%s\n", strError);
00404 goto endappinfo;
00405 }
00406 wdt_reset();
00407
00408
00409 if((appInfo->aip[0] & 0x20) != 0)
00410 {
00411 ddata = MakeByteArrayV(4,
00412 0x01, 0x02, 0x03, 0x04
00413 );
00414 response = SignDynamicData(convention, TC1, ddata);
00415 if(response == NULL)
00416 {
00417 fprintf(stderr, "%s\n", strError);
00418 goto endtdata;
00419 }
00420 wdt_reset();
00421 }
00422
00423
00424 pinTryCounter = GetDataObject(convention, TC1, PDO_PIN_TRY_COUNTER);
00425 if(pinTryCounter == NULL)
00426 {
00427 fprintf(stderr, "%s\n", strError);
00428 goto endtdata;
00429 }
00430 if(pinTryCounter->bytes[0] == 0)
00431 {
00432 fprintf(stderr, "%s\n", strPINTryExceeded);
00433 goto endpintry;
00434 }
00435 wdt_reset();
00436
00437 fprintf(stderr, "pin try:%d\n", pinTryCounter->bytes[0]);
00438 _delay_ms(1000);
00439 wdt_reset();
00440
00441
00442
00443
00444 pin = MakeByteArrayV(8, 0x24, 0x12, 0x34, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
00445 if(pin == NULL)
00446 {
00447 fprintf(stderr, "%s\n", strError);
00448 goto endpintry;
00449 }
00450 tmp = VerifyPlaintextPIN(convention, TC1, pin);
00451 if(tmp == 0)
00452 fprintf(stderr, "%s\n", strPINOK);
00453 else
00454 {
00455 fprintf(stderr, "%s\n", strPINBAD);
00456 goto endpin;
00457 }
00458 wdt_reset();
00459
00460
00461 acParams.amount[5] = 0x55;
00462 acParams.tvr[0] = 0x80;
00463 acParams.terminalCountryCode[0] = 0x08;
00464 acParams.terminalCountryCode[1] = 0x26;
00465 acParams.terminalCurrencyCode[0] = 0x08;
00466 acParams.terminalCurrencyCode[1] = 0x26;
00467 acParams.transactionDate[0] = 0x01;
00468 acParams.transactionDate[1] = 0x01;
00469 acParams.transactionDate[2] = 0x01;
00470 cdol = GetTLVFromRECORD(tData, 0x8C, 0);
00471 if(cdol == NULL)
00472 {
00473 fprintf(stderr, "%s\n", strError);
00474 goto endpin;
00475 }
00476
00477 if(response != NULL) FreeRAPDU(response);
00478 response = SendGenerateAC(convention, TC1, AC_REQ_ARQC, cdol, &acParams);
00479 if(response == NULL)
00480 {
00481 fprintf(stderr, "%s\n", strError);
00482 goto endpin;
00483 }
00484 wdt_reset();
00485
00486
00487 endpin:
00488 FreeByteArray(pin);
00489 endpintry:
00490 FreeByteArray(pinTryCounter);
00491 endtdata:
00492 FreeRECORD(tData);
00493 endappinfo:
00494 FreeAPPINFO(appInfo);
00495 if(offlineAuthData != NULL)
00496 FreeByteArray(offlineAuthData);
00497 endfci:
00498 FreeFCITemplate(fci);
00499 endtransaction:
00500 DeactivateICC();
00501 _delay_ms(2000);
00502
00503 return 0;
00504 }
00505
00521 uint8_t FilterGenerateAC()
00522 {
00523 uint8_t t_inverse = 0, t_TC1 = 0;
00524 uint8_t cInverse, cProto, cTC1, cTA3, cTB3;
00525 uint8_t tmp;
00526 uint8_t posCDOL1 = 0;
00527 uint8_t amount[12];
00528 uint8_t gotGAC = 0;
00529 CAPDU *cmd;
00530 RAPDU *response;
00531 RECORD *record;
00532 CRP *crp;
00533
00534 SleepUntilTerminalClock();
00535
00536
00537 wdt_enable(WDTO_4S);
00538
00539 if(InitSCDTransaction(t_inverse, t_TC1, &cInverse,
00540 &cProto, &cTC1, &cTA3, &cTB3))
00541 return RET_ERROR;
00542
00543
00544
00545
00546
00547 EIMSK &= ~(_BV(INT0));
00548 EICRA |= _BV(ISC01);
00549 EICRA &= ~(_BV(ISC00));
00550 EIFR |= _BV(INTF0);
00551 EIMSK |= _BV(INT0);
00552
00553
00554
00555 wdt_reset();
00556
00557 if(lcdAvailable)
00558 {
00559 InitLCD();
00560 fprintf(stderr, "\n");
00561 }
00562 else
00563 {
00564 DeactivateICC();
00565 return RET_ERROR;
00566 }
00567
00568
00569 while(posCDOL1 == 0)
00570 {
00571 wdt_reset();
00572 cmd = ReceiveT0Command(t_inverse, t_TC1);
00573 if(cmd == NULL) return RET_ERROR;
00574
00575 if((cmd->cmdHeader->cla & 0xF0) == 0 &&
00576 cmd->cmdHeader->ins == 0xB2)
00577 {
00578
00579 if(SendT0Command(cInverse, cTC1, cmd))
00580 {
00581 FreeCAPDU(cmd);
00582 return RET_ERROR;
00583 }
00584
00585 response = ReceiveT0Response(cInverse, cmd->cmdHeader);
00586 if(response == NULL)
00587 {
00588 FreeCAPDU(cmd);
00589 return RET_ERROR;
00590 }
00591
00592 if(response->repData != NULL)
00593 {
00594 record = ParseRECORD(response->repData, response->lenData);
00595 if(record == NULL)
00596 {
00597 FreeCAPDU(cmd);
00598 FreeRAPDU(response);
00599 return RET_ERROR;
00600 }
00601
00602 posCDOL1 = AmountPositionInCDOLRecord(record);
00603 FreeRECORD(record);
00604 record = NULL;
00605 }
00606
00607 if(SendT0Response(t_inverse, cmd->cmdHeader, response))
00608 {
00609 FreeCAPDU(cmd);
00610 FreeRAPDU(response);
00611 return RET_ERROR;
00612 }
00613 }
00614 else
00615 {
00616
00617 if(SendT0Command(cInverse, cTC1, cmd))
00618 {
00619 FreeCAPDU(cmd);
00620 return RET_ERROR;
00621 }
00622
00623 response = ForwardResponse(t_inverse, cInverse, cmd->cmdHeader);
00624 if(response == NULL)
00625 {
00626 FreeCAPDU(cmd);
00627 return RET_ERROR;
00628 }
00629
00630
00631 FreeCAPDU(cmd);
00632 FreeRAPDU(response);
00633 }
00634 }
00635
00636
00637 MCUSR = 0;
00638 wdt_disable();
00639
00640
00641 while(gotGAC == 0)
00642 {
00643 wdt_reset();
00644 cmd = ReceiveT0Command(t_inverse, t_TC1);
00645 if(cmd == NULL) return RET_ERROR;
00646
00647 if((cmd->cmdHeader->cla & 0xF0) == 0x80 &&
00648 cmd->cmdHeader->ins == 0xAE)
00649 {
00650
00651 if(cmd->cmdData == NULL)
00652 {
00653 FreeCAPDU(cmd);
00654 return RET_ERROR;
00655 }
00656
00657
00658
00659 gotGAC = 1;
00660
00661 posCDOL1--;
00662 amount[0] = (cmd->cmdData[posCDOL1] & 0xF0) >> 4;
00663 amount[1] = cmd->cmdData[posCDOL1] & 0x0F;
00664 amount[2] = (cmd->cmdData[posCDOL1 + 1] & 0xF0) >> 4;
00665 amount[3] = cmd->cmdData[posCDOL1 + 1] & 0x0F;
00666 amount[4] = (cmd->cmdData[posCDOL1 + 2] & 0xF0) >> 4;
00667 amount[5] = cmd->cmdData[posCDOL1 + 2] & 0x0F;
00668 amount[6] = (cmd->cmdData[posCDOL1 + 3] & 0xF0) >> 4;
00669 amount[7] = cmd->cmdData[posCDOL1 + 3] & 0x0F;
00670 amount[8] = (cmd->cmdData[posCDOL1 + 4] & 0xF0) >> 4;
00671 amount[9] = cmd->cmdData[posCDOL1 + 4] & 0x0F;
00672 amount[10] = (cmd->cmdData[posCDOL1 + 5] & 0xF0) >> 4;
00673 amount[11] = cmd->cmdData[posCDOL1 + 5] & 0x0F;
00674
00675
00676
00677
00678
00679
00680
00681 while(1){
00682 fprintf(stderr, "%s\n", strScroll);
00683 do{
00684 tmp = GetButton();
00685 _delay_ms(100);
00686 if(SendByteTerminalParity(0x60, t_inverse))
00687 {
00688 FreeCAPDU(cmd);
00689 return RET_ERROR;
00690 }
00691 }while((tmp & BUTTON_C) == 0);
00692 _delay_ms(100);
00693
00694 fprintf(stderr, "Amt:%1X%1X%1X%1X%1X%1X%1X%1X%1X,%1X%1X\n",
00695 amount[1],
00696 amount[2],
00697 amount[3],
00698 amount[4],
00699 amount[5],
00700 amount[6],
00701 amount[7],
00702 amount[8],
00703 amount[9],
00704 amount[10],
00705 amount[11]);
00706
00707 do{
00708 tmp = GetButton();
00709 _delay_ms(100);
00710 if(SendByteTerminalParity(0x60, t_inverse))
00711 {
00712 FreeCAPDU(cmd);
00713 return RET_ERROR;
00714 }
00715 }while((tmp & BUTTON_C) == 0);
00716 _delay_ms(100);
00717
00718 fprintf(stderr, "%s\n", strDecide);
00719 do{
00720 tmp = GetButton();
00721 _delay_ms(100);
00722 if(SendByteTerminalParity(0x60, t_inverse))
00723 {
00724 FreeCAPDU(cmd);
00725 return RET_ERROR;
00726 }
00727 }while(((tmp & BUTTON_A) == 0) &&
00728 ((tmp & BUTTON_C) == 0) &&
00729 ((tmp & BUTTON_D) == 0));
00730 _delay_ms(100);
00731
00732 if((tmp & BUTTON_D) != 0)
00733 {
00734 return RET_ERROR;
00735 }
00736
00737 if((tmp & BUTTON_A) != 0) break;
00738 }
00739
00740 wdt_enable(WDTO_4S);
00741
00742 }
00743
00744 if(SendT0Command(cInverse, cTC1, cmd))
00745 {
00746 FreeCAPDU(cmd);
00747 return RET_ERROR;
00748 }
00749
00750 response = ForwardResponse(t_inverse, cInverse, cmd->cmdHeader);
00751 FreeCAPDU(cmd);
00752
00753 if(response == NULL)
00754 {
00755 FreeRAPDU(response);
00756 return RET_ERROR;
00757 }
00758 FreeRAPDU(response);
00759 }
00760
00761
00762 while(1)
00763 {
00764 wdt_reset();
00765 crp = ExchangeCompleteData(t_inverse, cInverse, t_TC1, cTC1);
00766 if(crp == NULL) return RET_ERROR;
00767 FreeCRP(crp);
00768 }
00769
00770
00771 EIMSK &= ~(_BV(INT0));
00772
00773 return 0;
00774 }
00775
00794 uint8_t StorePIN()
00795 {
00796 uint8_t t_inverse = 0, t_TC1 = 0;
00797 uint8_t cInverse, cProto, cTC1, cTA3, cTB3;
00798 uint8_t tmp, len;
00799 CRP *crp;
00800
00801 SleepUntilTerminalClock();
00802
00803
00804 wdt_enable(WDTO_4S);
00805
00806 if(InitSCDTransaction(t_inverse, t_TC1, &cInverse,
00807 &cProto, &cTC1, &cTA3, &cTB3))
00808 return RET_ERROR;
00809
00810
00811
00812
00813
00814 EIMSK &= ~(_BV(INT0));
00815 EICRA |= _BV(ISC01);
00816 EICRA &= ~(_BV(ISC00));
00817 EIFR |= _BV(INTF0);
00818 EIMSK |= _BV(INT0);
00819
00820 wdt_reset();
00821
00822 #if LCD_ENABLED
00823 if(lcdAvailable)
00824 {
00825 InitLCD();
00826 fprintf(stderr, "\n");
00827 }
00828 #endif
00829
00830 while(1)
00831 {
00832 wdt_reset();
00833 crp = ExchangeCompleteData(t_inverse, cInverse, t_TC1, cTC1);
00834 if(crp == NULL) return RET_ERROR;
00835
00836
00837 MCUSR = 0;
00838 wdt_disable();
00839
00840
00841 if(crp->cmd->cmdHeader->cla == 0x00 &&
00842 crp->cmd->cmdHeader->ins == 0x20)
00843 {
00844
00845 if(crp->cmd->cmdHeader->p2 != 0x80 ||
00846 crp->cmd->cmdData == NULL)
00847 {
00848 if(lcdAvailable)
00849 fprintf(stderr, "Bad PIN cmd\n");
00850 wdt_enable(WDTO_15MS);
00851 return RET_ERROR;
00852 }
00853
00854 tmp = crp->cmd->cmdData[0];
00855 len = crp->cmd->cmdHeader->p3;
00856 if((tmp & 0xF0) != 0x20 || len != crp->cmd->lenData)
00857 {
00858 if(lcdAvailable)
00859 fprintf(stderr, "Bad PIN cmd\n");
00860 wdt_enable(WDTO_15MS);
00861 return RET_ERROR;
00862 }
00863
00864
00865 cli();
00866 eeprom_write_byte((uint8_t*)EEPROM_PIN, len);
00867 eeprom_write_block(crp->cmd->cmdData, (void*)(EEPROM_PIN + 1), len);
00868
00869
00870 #if LCD_ENABLED
00871 if(lcdAvailable)
00872 fprintf(stderr, "PIN stored\n");
00873 _delay_ms(1000);
00874 #endif
00875 wdt_enable(WDTO_4S);
00876 return 0;
00877 }
00878
00879 FreeCRP(crp);
00880 }
00881
00882
00883 EIMSK &= ~(_BV(INT0));
00884
00885 return 0;
00886 }
00887
00897 uint8_t ForwardAndChangePIN()
00898 {
00899 uint8_t t_inverse = 0, t_TC1 = 0, tdelay;
00900 uint8_t cInverse, cProto, cTC1, cTA3, cTB3;
00901 CAPDU *cmd, *tcmd = NULL;
00902 RAPDU *response;
00903 uint8_t sreg, len;
00904 uint8_t *pin;
00905
00906 SleepUntilTerminalClock();
00907
00908
00909 wdt_enable(WDTO_4S);
00910
00911
00912 sreg = SREG;
00913 cli();
00914 len = eeprom_read_byte((uint8_t*)EEPROM_PIN);
00915 SREG = sreg;
00916 pin = (uint8_t*)malloc(len * sizeof(uint8_t));
00917 if(pin == NULL) return RET_ERROR;
00918 eeprom_read_block(pin, (void*)(EEPROM_PIN + 1), len);
00919
00920
00921 wdt_reset();
00922
00923 if(InitSCDTransaction(t_inverse, t_TC1, &cInverse,
00924 &cProto, &cTC1, &cTA3, &cTB3))
00925 return RET_ERROR;
00926
00927
00928
00929
00930
00931 EIMSK &= ~(_BV(INT0));
00932 EICRA |= _BV(ISC01);
00933 EICRA &= ~(_BV(ISC00));
00934 EIFR |= _BV(INTF0);
00935 EIMSK |= _BV(INT0);
00936
00937 wdt_reset();
00938
00939 if(lcdAvailable)
00940 {
00941 InitLCD();
00942 fprintf(stderr, "\n");
00943 }
00944 else
00945 {
00946 DeactivateICC();
00947 return RET_ERROR;
00948 }
00949
00950
00951 while(1)
00952 {
00953 wdt_reset();
00954 cmd = ReceiveT0Command(t_inverse, t_TC1);
00955 if(cmd == NULL) return RET_ERROR;
00956
00957
00958 MCUSR = 0;
00959 wdt_disable();
00960
00961
00962 if(cmd->cmdHeader->cla == 0 &&
00963 cmd->cmdHeader->ins == 0x20 &&
00964 cmd->cmdHeader->p2 == 0x80 &&
00965 cmd->cmdData != NULL)
00966 {
00967
00968 tdelay = 1 + cTC1;
00969 tcmd = (CAPDU*)malloc(sizeof(CAPDU));
00970 tcmd->cmdHeader = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
00971 tcmd->cmdData = pin;
00972 tcmd->lenData = len;
00973 tcmd->cmdHeader->cla = cmd->cmdHeader->cla;
00974 tcmd->cmdHeader->ins = cmd->cmdHeader->ins;
00975 tcmd->cmdHeader->p1 = cmd->cmdHeader->p1;
00976 tcmd->cmdHeader->p2 = cmd->cmdHeader->p2;
00977 tcmd->cmdHeader->p3 = len;
00978
00979
00980 if(SendT0Command(cInverse, cTC1, tcmd))
00981 {
00982 FreeCAPDU(cmd);
00983 return RET_ERROR;
00984 }
00985
00986 wdt_enable(WDTO_4S);
00987
00988 response = ForwardResponse(t_inverse, cInverse, tcmd->cmdHeader);
00989 if(response == NULL)
00990 {
00991 FreeCAPDU(cmd);
00992 FreeCAPDU(tcmd);
00993 return RET_ERROR;
00994 }
00995
00996 FreeCAPDU(cmd);
00997 FreeCAPDU(tcmd);
00998 FreeRAPDU(response);
00999 }
01000 else
01001 {
01002 if(SendT0Command(cInverse, cTC1, cmd))
01003 {
01004 FreeCAPDU(cmd);
01005 return RET_ERROR;
01006 }
01007
01008 response = ForwardResponse(t_inverse, cInverse, cmd->cmdHeader);
01009 if(response == NULL)
01010 {
01011 FreeCAPDU(cmd);
01012 return RET_ERROR;
01013 }
01014
01015 FreeCAPDU(cmd);
01016 FreeRAPDU(response);
01017 }
01018
01019 }
01020
01021
01022 EIMSK &= ~(_BV(INT0));
01023
01024 return 0;
01025 }
01026
01035 uint8_t FilterAndLog()
01036 {
01037 uint8_t t_inverse = 0, t_TC1 = 0;
01038 uint8_t cInverse, cProto, cTC1, cTA3, cTB3;
01039 uint8_t tmp;
01040 uint8_t posCDOL1 = 0;
01041 uint8_t amount[12];
01042 uint8_t gotGAC = 0;
01043 CAPDU *cmd;
01044 RAPDU *response;
01045 RECORD *record;
01046 CRP *crp;
01047
01048 SleepUntilTerminalClock();
01049
01050
01051 wdt_enable(WDTO_4S);
01052
01053 if(InitSCDTransaction(t_inverse, t_TC1, &cInverse,
01054 &cProto, &cTC1, &cTA3, &cTB3))
01055 return RET_ERROR;
01056
01057
01058
01059
01060
01061 EIMSK &= ~(_BV(INT0));
01062 EICRA |= _BV(ISC01);
01063 EICRA &= ~(_BV(ISC00));
01064 EIFR |= _BV(INTF0);
01065 EIMSK |= _BV(INT0);
01066
01067
01068 wdt_reset();
01069
01070 if(lcdAvailable)
01071 {
01072 InitLCD();
01073 fprintf(stderr, "\n");
01074 }
01075 else
01076 {
01077 DeactivateICC();
01078 return RET_ERROR;
01079 }
01080
01081
01082 nCounter++;
01083
01084
01085 while(posCDOL1 == 0)
01086 {
01087 wdt_reset();
01088 cmd = ReceiveT0Command(t_inverse, t_TC1);
01089 if(cmd == NULL) return RET_ERROR;
01090
01091 if((cmd->cmdHeader->cla & 0xF0) == 0 &&
01092 cmd->cmdHeader->ins == 0xB2)
01093 {
01094
01095 if(SendT0Command(cInverse, cTC1, cmd))
01096 {
01097 FreeCAPDU(cmd);
01098 return RET_ERROR;
01099 }
01100
01101 response = ReceiveT0Response(cInverse, cmd->cmdHeader);
01102 if(response == NULL)
01103 {
01104 FreeCAPDU(cmd);
01105 return RET_ERROR;
01106 }
01107
01108 if(response->repData != NULL)
01109 {
01110 record = ParseRECORD(response->repData, response->lenData);
01111 if(record == NULL)
01112 {
01113 FreeCAPDU(cmd);
01114 FreeRAPDU(response);
01115 return RET_ERROR;
01116 }
01117
01118 posCDOL1 = AmountPositionInCDOLRecord(record);
01119 FreeRECORD(record);
01120 record = NULL;
01121 }
01122
01123 if(SendT0Response(t_inverse, cmd->cmdHeader, response))
01124 {
01125 FreeCAPDU(cmd);
01126 FreeRAPDU(response);
01127 return RET_ERROR;
01128 }
01129 #if DEBUG
01130 Led3On();
01131 #endif
01132 }
01133 else
01134 {
01135
01136 if(SendT0Command(cInverse, cTC1, cmd))
01137 {
01138 FreeCAPDU(cmd);
01139 return RET_ERROR;
01140 }
01141
01142 response = ForwardResponse(t_inverse, cInverse, cmd->cmdHeader);
01143 if(response == NULL)
01144 {
01145 FreeCAPDU(cmd);
01146 return RET_ERROR;
01147 }
01148
01149 #if DEBUG
01150 Led3On();
01151 #endif
01152 }
01153
01154 if(nTransactions < MAX_EXCHANGES)
01155 {
01156 transactionData[nTransactions] = (CRP*)malloc(sizeof(CRP));
01157 transactionData[nTransactions]->cmd = cmd;
01158 transactionData[nTransactions]->response = response;
01159 nTransactions++;
01160 }
01161 else
01162 {
01163 FreeCAPDU(cmd);
01164 FreeRAPDU(response);
01165 }
01166
01167 }
01168
01169
01170 MCUSR = 0;
01171 wdt_disable();
01172
01173
01174 while(gotGAC == 0)
01175 {
01176 wdt_reset();
01177 cmd = ReceiveT0Command(t_inverse, t_TC1);
01178 if(cmd == NULL) return RET_ERROR;
01179
01180 if((cmd->cmdHeader->cla & 0xF0) == 0x80 &&
01181 cmd->cmdHeader->ins == 0xAE)
01182 {
01183
01184 if(cmd->cmdData == NULL)
01185 {
01186 FreeCAPDU(cmd);
01187 return RET_ERROR;
01188 }
01189
01190
01191
01192 gotGAC = 1;
01193
01194 posCDOL1--;
01195 amount[0] = (cmd->cmdData[posCDOL1] & 0xF0) >> 4;
01196 amount[1] = cmd->cmdData[posCDOL1] & 0x0F;
01197 amount[2] = (cmd->cmdData[posCDOL1 + 1] & 0xF0) >> 4;
01198 amount[3] = cmd->cmdData[posCDOL1 + 1] & 0x0F;
01199 amount[4] = (cmd->cmdData[posCDOL1 + 2] & 0xF0) >> 4;
01200 amount[5] = cmd->cmdData[posCDOL1 + 2] & 0x0F;
01201 amount[6] = (cmd->cmdData[posCDOL1 + 3] & 0xF0) >> 4;
01202 amount[7] = cmd->cmdData[posCDOL1 + 3] & 0x0F;
01203 amount[8] = (cmd->cmdData[posCDOL1 + 4] & 0xF0) >> 4;
01204 amount[9] = cmd->cmdData[posCDOL1 + 4] & 0x0F;
01205 amount[10] = (cmd->cmdData[posCDOL1 + 5] & 0xF0) >> 4;
01206 amount[11] = cmd->cmdData[posCDOL1 + 5] & 0x0F;
01207
01208
01209
01210
01211
01212
01213
01214 while(1){
01215 fprintf(stderr, "%s\n", strScroll);
01216 do{
01217 tmp = GetButton();
01218 _delay_ms(100);
01219 if(SendByteTerminalParity(0x60, t_inverse))
01220 {
01221 FreeCAPDU(cmd);
01222 return RET_ERROR;
01223 }
01224 }while((tmp & BUTTON_C) == 0);
01225 _delay_ms(100);
01226
01227 fprintf(stderr, "Amt:%1X%1X%1X%1X%1X%1X%1X%1X%1X,%1X%1X\n",
01228 amount[1],
01229 amount[2],
01230 amount[3],
01231 amount[4],
01232 amount[5],
01233 amount[6],
01234 amount[7],
01235 amount[8],
01236 amount[9],
01237 amount[10],
01238 amount[11]);
01239
01240
01241 do{
01242 tmp = GetButton();
01243 _delay_ms(100);
01244 if(SendByteTerminalParity(0x60, t_inverse))
01245 {
01246 FreeCAPDU(cmd);
01247 return RET_ERROR;
01248 }
01249 }while((tmp & BUTTON_C) == 0);
01250 _delay_ms(100);
01251
01252 fprintf(stderr, "%s\n", strDecide);
01253 do{
01254 tmp = GetButton();
01255 _delay_ms(100);
01256 if(SendByteTerminalParity(0x60, t_inverse))
01257 {
01258 FreeCAPDU(cmd);
01259 return RET_ERROR;
01260 }
01261 }while(((tmp & BUTTON_A) == 0) &&
01262 ((tmp & BUTTON_C) == 0) &&
01263 ((tmp & BUTTON_D) == 0));
01264 _delay_ms(100);
01265
01266 if((tmp & BUTTON_D) != 0)
01267 {
01268
01269
01270 return RET_ERROR;
01271 }
01272
01273 if((tmp & BUTTON_A) != 0) break;
01274 }
01275
01276 wdt_enable(WDTO_4S);
01277
01278 }
01279
01280 if(SendT0Command(cInverse, cTC1, cmd))
01281 {
01282 FreeCAPDU(cmd);
01283 return RET_ERROR;
01284 }
01285
01286 response = ForwardResponse(t_inverse, cInverse, cmd->cmdHeader);
01287 if(response == NULL)
01288 {
01289 FreeCAPDU(cmd);
01290 FreeRAPDU(response);
01291 return RET_ERROR;
01292 }
01293
01294 if(nTransactions < MAX_EXCHANGES)
01295 {
01296 transactionData[nTransactions] = (CRP*)malloc(sizeof(CRP));
01297 transactionData[nTransactions]->cmd = cmd;
01298 transactionData[nTransactions]->response = response;
01299 nTransactions++;
01300 }
01301 else
01302 {
01303 FreeCAPDU(cmd);
01304 FreeRAPDU(response);
01305 }
01306
01307 }
01308
01309
01310 while(1)
01311 {
01312 wdt_reset();
01313 crp = ExchangeCompleteData(t_inverse, cInverse, t_TC1, cTC1);
01314 if(crp == NULL) return RET_ERROR;
01315
01316 if(nTransactions < MAX_EXCHANGES)
01317 transactionData[nTransactions++] = crp;
01318 else
01319 FreeCRP(crp);
01320 }
01321
01322
01323 EIMSK &= ~(_BV(INT0));
01324
01325 return 0;
01326 }
01327
01341 uint8_t ForwardData()
01342 {
01343 uint8_t t_inverse = 0, t_TC1 = 0;
01344 uint8_t cInverse, cProto, cTC1, cTA3, cTB3;
01345
01346 SleepUntilTerminalClock();
01347
01348
01349 wdt_enable(WDTO_4S);
01350
01351 if(InitSCDTransaction(t_inverse, t_TC1, &cInverse,
01352 &cProto, &cTC1, &cTA3, &cTB3))
01353 return RET_ERROR;
01354
01355
01356
01357
01358
01359 EIMSK &= ~(_BV(INT0));
01360 EICRA |= _BV(ISC01);
01361 EICRA &= ~(_BV(ISC00));
01362 EIFR |= _BV(INTF0);
01363 EIMSK |= _BV(INT0);
01364
01365 #if LCD_ENABLED
01366 if(lcdAvailable)
01367 {
01368 InitLCD();
01369 fprintf(stderr, "\n");
01370 }
01371 #endif
01372
01373
01374 nCounter++;
01375
01376 while(1)
01377 {
01378 transactionData[nTransactions++] = ExchangeCompleteData(t_inverse,
01379 cInverse, t_TC1, cTC1);
01380 if(transactionData[nTransactions-1] == NULL) return RET_ERROR;
01381 if(nTransactions == MAX_EXCHANGES) return RET_ERROR;
01382
01383
01384 MCUSR = 0;
01385 wdt_disable();
01386
01387 }
01388
01389
01390 EIMSK &= ~(_BV(INT0));
01391
01392 #if LCD_ENABLED
01393 fprintf(stderr, "%s\n", strDone);
01394 #endif
01395
01396 return 0;
01397 }
01398
01399
01405 void InitSCD()
01406 {
01407
01408 cli();
01409 EICRA = 0;
01410 EICRB = 0;
01411 EIFR = 0xFF;
01412 EIMSK = 0;
01413
01414
01415 MCUSR = 0;
01416 wdt_disable();
01417
01418
01419 DDRB = 0x00;
01420
01421 DDRC = 0x00;
01422 PORTC = 0x18;
01423
01424
01425 DDRD = 0x80;
01426 PORTD = 0x83;
01427
01428
01429 DDRF &= 0xF0;
01430 PORTF |= 0x0F;
01431
01432
01433 clock_prescale_set(clock_div_1);
01434
01435
01436 Led4On();
01437
01438 #if ICC_PRES_INT_ENABLE
01439
01440 EICRA |= _BV(ISC10);
01441 EICRA &= ~(_BV(ISC11));
01442 EIMSK |= _BV(INT1);
01443 #endif
01444
01445
01446 warmResetByte = eeprom_read_byte((uint8_t*)EEPROM_WARM_RESET);
01447
01448
01449 nCounter = eeprom_read_byte((uint8_t*)EEPROM_COUNTER);
01450
01451
01452 nTransactions = 0;
01453
01454
01455 if(CheckLCD())
01456 {
01457 stderr = NULL;
01458 lcdAvailable = 0;
01459 }
01460 else
01461 {
01462 stderr = &lcd_str;
01463 lcdAvailable = 1;
01464 }
01465
01466
01467 DDRC &= ~(_BV(PC5));
01468 PORTC &= ~(_BV(PC5));
01469 SetLCDState(0);
01470
01471
01472 power_adc_disable();
01473 power_spi_disable();
01474 power_twi_disable();
01475 power_usart1_disable();
01476 power_usb_disable();
01477
01478
01479 sei();
01480 }
01481
01486 void SleepUntilTerminalClock()
01487 {
01488 uint8_t sreg, lcdstate;
01489
01490 Write16bitRegister(&OCR3A, 100);
01491 Write16bitRegister(&TCNT3, 1);
01492 TCCR3A = 0;
01493 TIMSK3 = 0x02;
01494 TCCR3B = 0x0F;
01495 sreg = SREG;
01496
01497
01498 lcdstate = GetLCDState();
01499 if(lcdAvailable && lcdstate != 0) LCDOff();
01500 Led1Off();
01501 Led2Off();
01502 Led3Off();
01503 Led4Off();
01504
01505
01506 set_sleep_mode(SLEEP_MODE_IDLE);
01507 cli();
01508 sleep_enable();
01509 sei();
01510 sleep_cpu();
01511
01512
01513 sleep_disable();
01514 SREG = sreg;
01515 TIMSK3 = 0;
01516 TCCR3B = 0;
01517 Led4On();
01518 }
01519
01524 void SleepUntilCardInserted()
01525 {
01526 uint8_t sreg, lcdstate;
01527
01528
01529 lcdstate = GetLCDState();
01530 if(lcdAvailable && lcdstate != 0) LCDOff();
01531 Led1Off();
01532 Led2Off();
01533 Led3Off();
01534 Led4Off();
01535
01536
01537 sreg = SREG;
01538 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
01539 cli();
01540 sleep_enable();
01541 sei();
01542 sleep_cpu();
01543
01544
01545 sleep_disable();
01546 SREG = sreg;
01547 Led4On();
01548 }
01549
01550
01551
01557 ISR(INT0_vect)
01558 {
01559 uint8_t i;
01560 uint8_t *stream = NULL, lStream = 0;
01561 uint16_t addrStream;
01562 uint8_t addrHi, addrLo;
01563 uint8_t cmdstr[] = {0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
01564 uint8_t rspstr[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
01565 uint8_t appstr[] = {0xDD, 0xDD, 0xDD, 0xDD, 0xDD};
01566 uint8_t endstr[] = {0xBB, 0xBB, 0xBB, 0xBB, 0xBB};
01567
01568
01569 MCUSR = 0;
01570 wdt_disable();
01571
01572
01573 eeprom_write_byte((uint8_t*)EEPROM_COUNTER, nCounter);
01574
01575
01576 addrHi = eeprom_read_byte((uint8_t*)EEPROM_TLOG_POINTER_HI);
01577 addrLo = eeprom_read_byte((uint8_t*)EEPROM_TLOG_POINTER_LO);
01578 addrStream = ((addrHi << 8) | addrLo);
01579
01580 if(addrStream == 0xFFFF) addrStream = EEPROM_TLOG_DATA;
01581
01582
01583 if(nTransactions > 0 && addrStream < EEPROM_MAX_ADDRESS)
01584 {
01585
01586 eeprom_write_block(appstr, (void*)addrStream, 5);
01587 addrStream += 5;
01588 eeprom_write_byte((uint8_t*)addrStream, selected);
01589 addrStream += 1;
01590
01591
01592 for(i = 0; i < nTransactions; i++)
01593 {
01594
01595 stream = SerializeCommand(transactionData[i]->cmd, &lStream);
01596 if(stream != NULL)
01597 {
01598 eeprom_write_block(cmdstr, (void*)addrStream, 5);
01599 addrStream += 5;
01600 eeprom_write_block(stream, (void*)addrStream, lStream);
01601 free(stream);
01602 stream = NULL;
01603 addrStream += lStream;
01604 if(addrStream > EEPROM_MAX_ADDRESS) break;
01605 }
01606
01607
01608 stream = SerializeResponse(transactionData[i]->response, &lStream);
01609 if(stream != NULL)
01610 {
01611 eeprom_write_block(rspstr, (void*)addrStream, 5);
01612 addrStream += 5;
01613 eeprom_write_block(stream, (void*)addrStream, lStream);
01614 free(stream);
01615 stream = NULL;
01616 addrStream += lStream;
01617 if(addrStream > EEPROM_MAX_ADDRESS) break;
01618 }
01619
01620 FreeCRP(transactionData[i]);
01621 }
01622
01623
01624 eeprom_write_block(endstr, (void*)addrStream, 5);
01625 addrStream += 5;
01626
01627
01628 addrHi = (uint8_t)((addrStream >> 8) & 0x00FF);
01629 addrLo = (uint8_t)(addrStream & 0x00FF);
01630 addrLo += 8;
01631 addrLo = addrLo & 0xF8;
01632
01633 eeprom_write_byte((uint8_t*)EEPROM_TLOG_POINTER_HI, addrHi);
01634 eeprom_write_byte((uint8_t*)EEPROM_TLOG_POINTER_LO, addrLo);
01635 }
01636
01637 if(GetTerminalFreq())
01638 {
01639
01640 warmResetByte = eeprom_read_byte((uint8_t*)EEPROM_WARM_RESET);
01641
01642 if(warmResetByte == WARM_RESET_VALUE)
01643 {
01644
01645 eeprom_write_byte((uint8_t*)EEPROM_WARM_RESET, 0);
01646 while(EECR & _BV(EEPE));
01647 }
01648 else
01649 {
01650
01651 eeprom_write_byte((uint8_t*)EEPROM_WARM_RESET, WARM_RESET_VALUE);
01652 while(EECR & _BV(EEPE));
01653 }
01654 }
01655 else
01656 {
01657
01658 eeprom_write_byte((uint8_t*)EEPROM_WARM_RESET, 0);
01659 while(EECR & _BV(EEPE));
01660 }
01661
01662
01663 EIMSK &= ~(_BV(INT0));
01664
01665
01666 wdt_enable(WDTO_15MS);
01667 }
01668
01673 ISR(INT1_vect)
01674 {
01675 if(bit_is_set(PIND, PD1))
01676 {
01677 Led3On();
01678 }
01679 else
01680 {
01681 Led3Off();
01682 DeactivateICC();
01683 }
01684
01685 }
01686
01692 ISR(TIMER3_COMPA_vect, ISR_NAKED)
01693 {
01694 reti();
01695 }
01696
01700 void TestHardware()
01701 {
01702 #if LCD_ENABLED
01703 char* strBA = "Press BA";
01704 char* strBB = "Press BB";
01705 char* strBC = "Press BC";
01706 char* strBD = "Press BD";
01707 char* strAOK = "All fine!";
01708 #endif
01709
01710
01711 Led1On();
01712 _delay_ms(50);
01713 Led1Off();
01714 Led2On();
01715 _delay_ms(50);
01716 Led2Off();
01717 Led3On();
01718 _delay_ms(50);
01719 Led3Off();
01720 Led4On();
01721 _delay_ms(50);
01722 Led4Off();
01723
01724 #if LCD_ENABLED
01725 if(lcdAvailable)
01726 {
01727 InitLCD();
01728 fprintf(stderr, "\n");
01729
01730 WriteStringLCD(strBA, strlen(strBA));
01731 while(bit_is_set(PINF, PF3));
01732
01733 WriteStringLCD(strBB, strlen(strBB));
01734 while(bit_is_set(PINF, PF2));
01735
01736 WriteStringLCD(strBC, strlen(strBC));
01737 while(bit_is_set(PINF, PF1));
01738
01739 WriteStringLCD(strBD, strlen(strBD));
01740 while(bit_is_set(PINF, PF0));
01741
01742 WriteStringLCD(strAOK, strlen(strAOK));
01743 }
01744 #endif
01745 }
01746
01763 uint8_t FilterGenerateACSimple()
01764 {
01765 uint8_t t_inverse = 0, t_TC1 = 0;
01766 uint8_t cInverse, cProto, cTC1, cTA3, cTB3;
01767 uint8_t ba, bb;
01768 uint8_t amount[12];
01769 CAPDU *cmd;
01770 RAPDU *response;
01771 CRP *crp;
01772
01773
01774
01775
01776
01777 EIMSK &= ~(_BV(INT0));
01778 EICRA |= _BV(ISC01);
01779 EICRA &= ~(_BV(ISC00));
01780 EIFR |= _BV(INTF0);
01781 EIMSK |= _BV(INT0);
01782
01783 if(InitSCDTransaction(t_inverse, t_TC1, &cInverse,
01784 &cProto, &cTC1, &cTA3, &cTB3))
01785 return RET_ERROR;
01786
01787 if(lcdAvailable)
01788 {
01789 InitLCD();
01790 fprintf(stderr, "\n");
01791 }
01792 else
01793 {
01794 DeactivateICC();
01795 return RET_ERROR;
01796 }
01797
01798
01799 while(1)
01800 {
01801 cmd = ReceiveT0Command(t_inverse, t_TC1);
01802 if(cmd == NULL) return RET_ERROR;
01803
01804 if((cmd->cmdHeader->cla & 0xF0) == 0x80 && cmd->cmdHeader->ins == 0xAE)
01805 {
01806
01807
01808
01809 amount[0] = (cmd->cmdData[0] & 0xF0) >> 4;
01810 amount[1] = cmd->cmdData[0] & 0x0F;
01811 amount[2] = (cmd->cmdData[1] & 0xF0) >> 4;
01812 amount[3] = cmd->cmdData[1] & 0x0F;
01813 amount[4] = (cmd->cmdData[2] & 0xF0) >> 4;
01814 amount[5] = cmd->cmdData[2] & 0x0F;
01815 amount[6] = (cmd->cmdData[3] & 0xF0) >> 4;
01816 amount[7] = cmd->cmdData[3] & 0x0F;
01817 amount[8] = (cmd->cmdData[4] & 0xF0) >> 4;
01818 amount[9] = cmd->cmdData[4] & 0x0F;
01819 amount[10] = (cmd->cmdData[5] & 0xF0) >> 4;
01820 amount[11] = cmd->cmdData[5] & 0x0F;
01821
01822
01823 do{
01824 fprintf(stderr, "Amt:%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d\n",
01825 amount[0],
01826 amount[1],
01827 amount[2],
01828 amount[3],
01829 amount[4],
01830 amount[5],
01831 amount[6],
01832 amount[7],
01833 amount[8],
01834 amount[9],
01835 amount[10],
01836 amount[11]);
01837 _delay_ms(500);
01838
01839
01840 if(SendByteTerminalParity(0x60, t_inverse))
01841 {
01842 FreeCAPDU(cmd);
01843 return RET_ERROR;
01844 }
01845
01846
01847 fprintf(stderr, "Authorize?\n");
01848 _delay_ms(500);
01849
01850
01851 if(SendByteTerminalParity(0x60, t_inverse))
01852 {
01853 FreeCAPDU(cmd);
01854 return RET_ERROR;
01855 }
01856
01857 fprintf(stderr, "BA = YES BB = NO\n");
01858 _delay_ms(500);
01859
01860 ba = GetButtonA();
01861 bb = GetButtonB();
01862
01863
01864 if(SendByteTerminalParity(0x60, t_inverse))
01865 {
01866 FreeCAPDU(cmd);
01867 return RET_ERROR;
01868 }
01869 }while(ba && bb);
01870
01871 if(!bb)
01872 wdt_enable(WDTO_15MS);
01873 }
01874
01875
01876 if(SendT0Command(cInverse, cTC1, cmd))
01877 {
01878 FreeCAPDU(cmd);
01879 return RET_ERROR;
01880 }
01881
01882 response = ForwardResponse(t_inverse, cInverse, cmd->cmdHeader);
01883 FreeCAPDU(cmd);
01884
01885 if(response == NULL)
01886 {
01887 FreeRAPDU(response);
01888 return RET_ERROR;
01889 }
01890 FreeRAPDU(response);
01891 }
01892
01893
01894 while(1)
01895 {
01896 crp = ExchangeCompleteData(t_inverse, cInverse, t_TC1, cTC1);
01897 if(crp == NULL) return RET_ERROR;
01898 FreeCRP(crp);
01899 }
01900
01901
01902 EIMSK &= ~(_BV(INT0));
01903
01904 return 0;
01905 }
01906
01907
01908
01917 void TestSCDTerminal()
01918 {
01919 char strLCD[16];
01920 uint8_t tmpa;
01921
01922
01923 StartCounterTerminal();
01924
01925
01926 while(ReadCounterTerminal() < 100);
01927 Led1On();
01928 while(GetResetStateTerminal() == 0);
01929 Led2On();
01930 LoopTerminalETU(10);
01931 SendT0ATRTerminal(0, 0x0F);
01932 Led1Off();
01933
01934
01935 #if LCD_ENABLED
01936 if(lcdAvailable)
01937 {
01938 InitLCD();
01939 fprintf(stderr, "\n");
01940 WriteStringLCD(strATRSent, strlen(strATRSent));
01941 }
01942 #endif
01943
01944 while(1)
01945 {
01946
01947 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[0]);
01948 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[1]);
01949 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[2]);
01950 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[3]);
01951 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[4]);
01952
01953 strLCD[5] = 0;
01954
01955 Led1On();
01956 Led2Off();
01957
01958
01959 LoopTerminalETU(20);
01960
01961 SendByteTerminalParity(0xA4, 0);
01962
01963 Led1Off();
01964 Led2On();
01965
01966
01967 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[0]);
01968 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[1]);
01969 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[2]);
01970 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[3]);
01971 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[4]);
01972 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[5]);
01973 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[6]);
01974 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[7]);
01975 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[8]);
01976 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[9]);
01977 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[10]);
01978 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[11]);
01979 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[12]);
01980 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[13]);
01981 strLCD[14] = 0;
01982
01983 Led1On();
01984 Led2Off();
01985
01986 #if LCD_ENABLED
01987 if(lcdAvailable)
01988 {
01989 if(tmpa != 0)
01990 WriteStringLCD(strError, strlen(strError));
01991 else
01992 WriteStringLCD(strLCD, 14);
01993 }
01994 #endif
01995
01996
01997 SendByteTerminalParity(0x61, 0);
01998 LoopTerminalETU(2);
01999 SendByteTerminalParity(0x04, 0);
02000
02001 Led1Off();
02002 Led2On();
02003
02004
02005 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[0]);
02006 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[1]);
02007 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[2]);
02008 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[3]);
02009 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[4]);
02010 strLCD[5] = 0;
02011
02012 Led1On();
02013 Led2Off();
02014
02015
02016 LoopTerminalETU(20);
02017 SendByteTerminalParity(0xC0, 0);
02018 LoopTerminalETU(2);
02019
02020 SendByteTerminalParity(0xDE, 0);
02021 LoopTerminalETU(2);
02022
02023 SendByteTerminalParity(0xAD, 0);
02024 LoopTerminalETU(2);
02025
02026 SendByteTerminalParity(0xBE, 0);
02027 LoopTerminalETU(2);
02028
02029 SendByteTerminalParity(0xEF, 0);
02030 LoopTerminalETU(2);
02031
02032 SendByteTerminalParity(0x90, 0);
02033 LoopTerminalETU(2);
02034
02035 SendByteTerminalParity(0x00, 0);
02036
02037 Led1Off();
02038 Led2On();
02039
02040 #if LCD_ENABLED
02041 if(lcdAvailable)
02042 WriteStringLCD(strDataSent, strlen(strDataSent));
02043 #endif
02044 }
02045 }
02046
02053 void TestSCDICC()
02054 {
02055 uint8_t inverse, proto, TC1, TA3, TB3;
02056 uint8_t byte;
02057
02058
02059 if(ResetICC(0, &inverse, &proto, &TC1, &TA3, &TB3)) return;
02060
02061
02062 LoopICCETU(5);
02063 SendByteICCParity(0x00, inverse);
02064 LoopICCETU(2);
02065 SendByteICCParity(0xA4, inverse);
02066 LoopICCETU(2);
02067 SendByteICCParity(0x04, inverse);
02068 LoopICCETU(2);
02069 SendByteICCParity(0x00, inverse);
02070 LoopICCETU(2);
02071 SendByteICCParity(0x0E, inverse);
02072
02073
02074 LoopICCETU(1);
02075 GetByteICCParity(inverse, &byte);
02076 if(byte != 0xA4) return;
02077
02078
02079 LoopICCETU(5);
02080 SendByteICCParity(0x31, inverse);
02081 LoopICCETU(2);
02082 SendByteICCParity(0x50, inverse);
02083 LoopICCETU(2);
02084 SendByteICCParity(0x41, inverse);
02085 LoopICCETU(2);
02086 SendByteICCParity(0x59, inverse);
02087 LoopICCETU(2);
02088 SendByteICCParity(0x2E, inverse);
02089 LoopICCETU(2);
02090 SendByteICCParity(0x53, inverse);
02091 LoopICCETU(2);
02092 SendByteICCParity(0x59, inverse);
02093 LoopICCETU(2);
02094 SendByteICCParity(0x53, inverse);
02095 LoopICCETU(2);
02096 SendByteICCParity(0x2E, inverse);
02097 LoopICCETU(2);
02098 SendByteICCParity(0x44, inverse);
02099 LoopICCETU(2);
02100 SendByteICCParity(0x44, inverse);
02101 LoopICCETU(2);
02102 SendByteICCParity(0x46, inverse);
02103 LoopICCETU(2);
02104 SendByteICCParity(0x30, inverse);
02105 LoopICCETU(2);
02106 SendByteICCParity(0x31, inverse);
02107
02108
02109 LoopICCETU(1);
02110 GetByteICCParity(inverse, &byte);
02111 if(byte != 0x61) return;
02112 LoopICCETU(1);
02113 GetByteICCParity(inverse, &byte);
02114
02115
02116 LoopICCETU(5);
02117 SendByteICCParity(0x00, inverse);
02118 LoopICCETU(2);
02119 SendByteICCParity(0xC0, inverse);
02120 LoopICCETU(2);
02121 SendByteICCParity(0x00, inverse);
02122 LoopICCETU(2);
02123 SendByteICCParity(0x00, inverse);
02124 LoopICCETU(2);
02125 SendByteICCParity(byte, inverse);
02126
02127
02128 Led1On();
02129 #if LCD_ENABLED
02130 if(lcdAvailable)
02131 {
02132 InitLCD();
02133 fprintf(stderr, "\n");
02134 WriteStringLCD(strDataSent, strlen(strDataSent));
02135 }
02136 #endif
02137 }
02138
02142 void SwitchLeds()
02143 {
02144 while(1)
02145 {
02146 _delay_ms(500);
02147 Led1On();
02148 Led2Off();
02149 _delay_ms(500);
02150 Led1Off();
02151 Led2On();
02152 }
02153 }