00001
00036
00037
00038
00039 #ifndef __DELAY_BACKWARD_COMPATIBLE__
00040 #define __DELAY_BACKWARD_COMPATIBLE__
00041 #endif
00042
00043 #include <avr/io.h>
00044 #include <avr/interrupt.h>
00045 #include <avr/sleep.h>
00046 #include <avr/power.h>
00047 #include <avr/eeprom.h>
00048 #include <string.h>
00049 #include <util/delay.h>
00050 #include <util/delay_basic.h>
00051 #include <stdlib.h>
00052 #include <avr/wdt.h>
00053
00054 #include "apps.h"
00055 #include "emv.h"
00056 #include "scd_hal.h"
00057 #include "scd_io.h"
00058 #include "scd.h"
00059 #include "scd_logger.h"
00060 #include "utils.h"
00061 #include "emv_values.h"
00062 #include "scd_values.h"
00063 #include "VirtualSerial.h"
00064 #include "serial.h"
00065
00067 #define LCD_ENABLED 1
00068
00070 #define DEBUG 0
00071
00073 #define ICC_PRES_INT_ENABLE 1
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #if LCD_ENABLED
00085 static char* strATRSent = "ATR Sent";
00086 static char* strError = "Error Ocurred";
00087 static char* strDataSent = "Data Sent";
00088 static char* strScroll = "BC to scroll";
00089 static char* strSelect = "BD to select";
00090 static char* strAvailable = "Avail. apps:";
00091 #endif
00092 log_struct_t scd_logger;
00093
00094
00095 uint8_t warmResetByte;
00096 uint8_t lcdAvailable;
00097 uint8_t nCounter;
00098 uint8_t selected;
00099 uint8_t bootkey;
00100 uint16_t revision = 0x24;
00101
00102
00103 FILE lcd_str = FDEV_SETUP_STREAM(LcdPutchar, NULL, _FDEV_SETUP_WRITE);
00104
00105
00109 int main(void)
00110 {
00111 uint8_t sreg;
00112
00113
00114 InitSCD();
00115
00116
00117
00118
00119
00120 if(GetButtonB() == 0)
00121 {
00122 selected = SelectApplication();
00123
00124 if(selected == APP_ERASE_EEPROM)
00125 {
00126 Led2On();
00127 ResetEEPROM();
00128 Led2Off();
00129 wdt_enable(WDTO_15MS);
00130 }
00131 else
00132 {
00133 sreg = SREG;
00134 cli();
00135 eeprom_write_byte((uint8_t*)EEPROM_APPLICATION, selected);
00136 SREG = sreg;
00137 }
00138
00139
00140 ResetCounter();
00141
00142
00143 wdt_enable(WDTO_15MS);
00144 }
00145 else
00146 {
00147 sreg = SREG;
00148 cli();
00149 selected = eeprom_read_byte((uint8_t*)EEPROM_APPLICATION);
00150 SREG = sreg;
00151 }
00152
00153
00154
00155 while(1)
00156 {
00157 switch(selected)
00158 {
00159 case APP_VIRTUAL_SERIAL_PORT:
00160 VirtualSerial(&scd_logger);
00161 break;
00162
00163 case APP_FORWARD:
00164 ForwardData(&scd_logger);
00165 break;
00166
00167 case APP_FILTER_GENERATEAC:
00168 FilterGenerateAC(&scd_logger);
00169 break;
00170
00171 case APP_TERMINAL:
00172 Terminal(&scd_logger);
00173 break;
00174
00175 case APP_LOG_GENERATE_AC:
00176 ForwardDataLogAC(&scd_logger);
00177 break;
00178
00179 case APP_SERIAL_PORT:
00180 SerialInterface(103);
00181 break;
00182
00183
00184 default:
00185 selected = APP_VIRTUAL_SERIAL_PORT;
00186 eeprom_write_byte((uint8_t*)EEPROM_APPLICATION, selected);
00187 VirtualSerial(&scd_logger);
00188 }
00189 }
00190
00191
00192
00193
00194 SwitchLeds();
00195 }
00196
00210 uint8_t SelectApplication()
00211 {
00212 volatile uint8_t tmp;
00213 uint8_t i;
00214
00215 if(!lcdAvailable) return 0;
00216
00217 InitLCD();
00218 fprintf(stderr, "\n");
00219
00220 while(1){
00221 fprintf(stderr, "%s\n", strScroll);
00222 do{
00223 tmp = GetButton();
00224 }while((tmp & BUTTON_C) == 0);
00225 _delay_ms(500);
00226
00227 fprintf(stderr, "%s\n", strSelect);
00228 do{
00229 tmp = GetButton();
00230 }while((tmp & BUTTON_C) == 0);
00231 _delay_ms(500);
00232
00233 fprintf(stderr, "%s\n", strAvailable);
00234 do{
00235 tmp = GetButton();
00236 }while((tmp & BUTTON_C) == 0);
00237 _delay_ms(500);
00238
00239 for(i = 0; i < APPLICATION_COUNT; i++)
00240 {
00241 fprintf(stderr, "%s\n", appStrings[i]);
00242 while(1)
00243 {
00244 tmp = GetButton();
00245 if((tmp & BUTTON_D) != 0) return (i + 1);
00246 if((tmp & BUTTON_C) != 0) break;
00247 }
00248 _delay_ms(500);
00249 }
00250 }
00251
00252 return 0;
00253 }
00254
00255
00261 void InitSCD()
00262 {
00263
00264 cli();
00265 EICRA = 0;
00266 EICRB = 0;
00267 EIFR = 0xFF;
00268 EIMSK = 0;
00269
00270
00271 DisableWDT();
00272
00273
00274 ResetLogger(&scd_logger);
00275
00276
00277
00278 SetCounter(eeprom_read_dword((uint32_t*)EEPROM_TIMER_T2) + 4);
00279
00280
00281 DDRB = 0x00;
00282
00283 DDRC = 0x00;
00284 PORTC = 0x18;
00285
00286
00287 DDRD = 0x80;
00288 PORTD = 0x83;
00289
00290
00291 DDRF &= 0xF0;
00292 PORTF |= 0x0F;
00293
00294
00295 clock_prescale_set(clock_div_1);
00296
00297
00298 StartTimerT2();
00299
00300
00301 Led4On();
00302
00303
00304
00305
00306
00307
00308 warmResetByte = eeprom_read_byte((uint8_t*)EEPROM_WARM_RESET);
00309
00310
00311 nCounter = eeprom_read_byte((uint8_t*)EEPROM_COUNTER);
00312
00313
00314 if(CheckLCD())
00315 {
00316 stderr = NULL;
00317 lcdAvailable = 0;
00318 }
00319 else
00320 {
00321 stderr = &lcd_str;
00322 lcdAvailable = 1;
00323
00324 LCDOff();
00325 }
00326
00327
00328 power_adc_disable();
00329 power_spi_disable();
00330 power_twi_disable();
00331 power_usart1_disable();
00332 power_usb_disable();
00333
00334
00335 sei();
00336
00337
00338 EIMSK &= ~(_BV(INT0));
00339 EIMSK &= ~(_BV(INT1));
00340 }
00341
00342
00343
00344
00350 ISR(INT0_vect)
00351 {
00352
00353 DisableWDT();
00354
00355
00356 DisableTerminalResetInterrupt();
00357
00358
00359 LogByte1(&scd_logger, LOG_TERMINAL_RST_LOW, 0);
00360
00361
00362 WriteLogEEPROM(&scd_logger);
00363 ResetLogger(&scd_logger);
00364
00365
00366 if(GetTerminalFreq())
00367 {
00368
00369 warmResetByte = eeprom_read_byte((uint8_t*)EEPROM_WARM_RESET);
00370
00371 if(warmResetByte == WARM_RESET_VALUE)
00372 {
00373
00374 eeprom_write_byte((uint8_t*)EEPROM_WARM_RESET, 0);
00375 while(EECR & _BV(EEPE));
00376 }
00377 else
00378 {
00379
00380 eeprom_write_byte((uint8_t*)EEPROM_WARM_RESET, WARM_RESET_VALUE);
00381 while(EECR & _BV(EEPE));
00382 }
00383 }
00384 else
00385 {
00386 eeprom_write_byte((uint8_t*)EEPROM_WARM_RESET, 0);
00387 while(EECR & _BV(EEPE));
00388 }
00389
00390
00391 wdt_enable(WDTO_15MS);
00392
00393
00394 eeprom_update_dword((uint32_t*)EEPROM_TIMER_T2, GetCounter());
00395 }
00396
00401 ISR(INT1_vect)
00402 {
00403 if(bit_is_set(PIND, PD1))
00404 {
00405 Led3On();
00406 }
00407 else
00408 {
00409 Led3Off();
00410 DeactivateICC();
00411 }
00412
00413 }
00414
00418 ISR(WDT_vect)
00419 {
00420
00421 LogByte1(&scd_logger, LOG_WDT_RESET, 0);
00422
00423
00424 WriteLogEEPROM(&scd_logger);
00425 ResetLogger(&scd_logger);
00426 }
00427
00428
00434 ISR(TIMER3_COMPA_vect, ISR_NAKED)
00435 {
00436 reti();
00437 }
00438
00453
00454
00455
00456
00457
00465 void BootloaderJumpCheck()
00466 {
00467 uint16_t bootloader_addr;
00468 uint8_t fuse_high;
00469
00470
00471 wdt_disable();
00472
00473
00474 if ((MCUSR & (1<<WDRF)) && (bootkey == MAGIC_BOOT_KEY))
00475 {
00476 bootkey = 0;
00477
00478 fuse_high = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
00479 fuse_high = (fuse_high & 0x07) >> 1;
00480 if(fuse_high == 0)
00481 bootloader_addr = 0xF000;
00482 else if(fuse_high == 1)
00483 bootloader_addr = 0xF800;
00484 else if(fuse_high == 2)
00485 bootloader_addr = 0xFC00;
00486 else if(fuse_high == 3)
00487 bootloader_addr = 0xFE00;
00488
00489 ((void (*)(void))bootloader_addr)();
00490 }
00491 }
00492
00496 void TestHardware()
00497 {
00498 #if LCD_ENABLED
00499 char* strBA = "Press BA";
00500 char* strBB = "Press BB";
00501 char* strBC = "Press BC";
00502 char* strBD = "Press BD";
00503 char* strAOK = "All fine!";
00504 #endif
00505
00506
00507 Led1On();
00508 _delay_ms(50);
00509 Led1Off();
00510 Led2On();
00511 _delay_ms(50);
00512 Led2Off();
00513 Led3On();
00514 _delay_ms(50);
00515 Led3Off();
00516 Led4On();
00517 _delay_ms(50);
00518 Led4Off();
00519
00520 #if LCD_ENABLED
00521 if(lcdAvailable)
00522 {
00523 InitLCD();
00524 fprintf(stderr, "\n");
00525
00526 WriteStringLCD(strBA, strlen(strBA));
00527 while(bit_is_set(PINF, PF3));
00528
00529 WriteStringLCD(strBB, strlen(strBB));
00530 while(bit_is_set(PINF, PF2));
00531
00532 WriteStringLCD(strBC, strlen(strBC));
00533 while(bit_is_set(PINF, PF1));
00534
00535 WriteStringLCD(strBD, strlen(strBD));
00536 while(bit_is_set(PINF, PF0));
00537
00538 WriteStringLCD(strAOK, strlen(strAOK));
00539 }
00540 #endif
00541 }
00542
00551 void TestSCDTerminal()
00552 {
00553 char strLCD[16];
00554 uint8_t tmpa;
00555
00556
00557 StartCounterTerminal();
00558
00559
00560 while(ReadCounterTerminal() < 100);
00561 Led1On();
00562 while(GetTerminalResetLine() == 0);
00563 Led2On();
00564 LoopTerminalETU(10);
00565 SendT0ATRTerminal(0, 0x0F, NULL);
00566 Led1Off();
00567
00568
00569 #if LCD_ENABLED
00570 if(lcdAvailable)
00571 {
00572 InitLCD();
00573 fprintf(stderr, "\n");
00574 WriteStringLCD(strATRSent, strlen(strATRSent));
00575 }
00576 #endif
00577
00578 while(1)
00579 {
00580
00581 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[0], MAX_WAIT_TERMINAL);
00582 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[1], MAX_WAIT_TERMINAL);
00583 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[2], MAX_WAIT_TERMINAL);
00584 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[3], MAX_WAIT_TERMINAL);
00585 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[4], MAX_WAIT_TERMINAL);
00586
00587 strLCD[5] = 0;
00588
00589 Led1On();
00590 Led2Off();
00591
00592
00593 LoopTerminalETU(20);
00594
00595 SendByteTerminalParity(0xA4, 0);
00596
00597 Led1Off();
00598 Led2On();
00599
00600
00601 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[0], MAX_WAIT_TERMINAL);
00602 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[1], MAX_WAIT_TERMINAL);
00603 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[2], MAX_WAIT_TERMINAL);
00604 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[3], MAX_WAIT_TERMINAL);
00605 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[4], MAX_WAIT_TERMINAL);
00606 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[5], MAX_WAIT_TERMINAL);
00607 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[6], MAX_WAIT_TERMINAL);
00608 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[7], MAX_WAIT_TERMINAL);
00609 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[8], MAX_WAIT_TERMINAL);
00610 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[9], MAX_WAIT_TERMINAL);
00611 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[10], MAX_WAIT_TERMINAL);
00612 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[11], MAX_WAIT_TERMINAL);
00613 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[12], MAX_WAIT_TERMINAL);
00614 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[13], MAX_WAIT_TERMINAL);
00615 strLCD[14] = 0;
00616
00617 Led1On();
00618 Led2Off();
00619
00620 #if LCD_ENABLED
00621 if(lcdAvailable)
00622 {
00623 if(tmpa != 0)
00624 WriteStringLCD(strError, strlen(strError));
00625 else
00626 WriteStringLCD(strLCD, 14);
00627 }
00628 #endif
00629
00630
00631 SendByteTerminalParity(0x61, 0);
00632 LoopTerminalETU(2);
00633 SendByteTerminalParity(0x04, 0);
00634
00635 Led1Off();
00636 Led2On();
00637
00638
00639 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[0], MAX_WAIT_TERMINAL);
00640 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[1], MAX_WAIT_TERMINAL);
00641 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[2], MAX_WAIT_TERMINAL);
00642 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[3], MAX_WAIT_TERMINAL);
00643 tmpa = GetByteTerminalParity(0, (uint8_t*)&strLCD[4], MAX_WAIT_TERMINAL);
00644 strLCD[5] = 0;
00645
00646 Led1On();
00647 Led2Off();
00648
00649
00650 LoopTerminalETU(20);
00651 SendByteTerminalParity(0xC0, 0);
00652 LoopTerminalETU(2);
00653
00654 SendByteTerminalParity(0xDE, 0);
00655 LoopTerminalETU(2);
00656
00657 SendByteTerminalParity(0xAD, 0);
00658 LoopTerminalETU(2);
00659
00660 SendByteTerminalParity(0xBE, 0);
00661 LoopTerminalETU(2);
00662
00663 SendByteTerminalParity(0xEF, 0);
00664 LoopTerminalETU(2);
00665
00666 SendByteTerminalParity(0x90, 0);
00667 LoopTerminalETU(2);
00668
00669 SendByteTerminalParity(0x00, 0);
00670
00671 Led1Off();
00672 Led2On();
00673
00674 #if LCD_ENABLED
00675 if(lcdAvailable)
00676 WriteStringLCD(strDataSent, strlen(strDataSent));
00677 #endif
00678 }
00679 }
00680
00689 void TestSCDICC(log_struct_t *logger)
00690 {
00691 uint8_t inverse, proto, TC1, TA3, TB3;
00692 uint8_t byte;
00693
00694
00695 if(ResetICC(0, &inverse, &proto, &TC1, &TA3, &TB3, logger)) return;
00696
00697
00698 LoopICCETU(5);
00699 SendByteICCParity(0x00, inverse);
00700 LoopICCETU(2);
00701 SendByteICCParity(0xA4, inverse);
00702 LoopICCETU(2);
00703 SendByteICCParity(0x04, inverse);
00704 LoopICCETU(2);
00705 SendByteICCParity(0x00, inverse);
00706 LoopICCETU(2);
00707 SendByteICCParity(0x0E, inverse);
00708
00709
00710 LoopICCETU(1);
00711 GetByteICCParity(inverse, &byte);
00712 if(byte != 0xA4) return;
00713
00714
00715 LoopICCETU(5);
00716 SendByteICCParity(0x31, inverse);
00717 LoopICCETU(2);
00718 SendByteICCParity(0x50, inverse);
00719 LoopICCETU(2);
00720 SendByteICCParity(0x41, inverse);
00721 LoopICCETU(2);
00722 SendByteICCParity(0x59, inverse);
00723 LoopICCETU(2);
00724 SendByteICCParity(0x2E, inverse);
00725 LoopICCETU(2);
00726 SendByteICCParity(0x53, inverse);
00727 LoopICCETU(2);
00728 SendByteICCParity(0x59, inverse);
00729 LoopICCETU(2);
00730 SendByteICCParity(0x53, inverse);
00731 LoopICCETU(2);
00732 SendByteICCParity(0x2E, inverse);
00733 LoopICCETU(2);
00734 SendByteICCParity(0x44, inverse);
00735 LoopICCETU(2);
00736 SendByteICCParity(0x44, inverse);
00737 LoopICCETU(2);
00738 SendByteICCParity(0x46, inverse);
00739 LoopICCETU(2);
00740 SendByteICCParity(0x30, inverse);
00741 LoopICCETU(2);
00742 SendByteICCParity(0x31, inverse);
00743
00744
00745 LoopICCETU(1);
00746 GetByteICCParity(inverse, &byte);
00747 if(byte != 0x61) return;
00748 LoopICCETU(1);
00749 GetByteICCParity(inverse, &byte);
00750
00751
00752 LoopICCETU(5);
00753 SendByteICCParity(0x00, inverse);
00754 LoopICCETU(2);
00755 SendByteICCParity(0xC0, inverse);
00756 LoopICCETU(2);
00757 SendByteICCParity(0x00, inverse);
00758 LoopICCETU(2);
00759 SendByteICCParity(0x00, inverse);
00760 LoopICCETU(2);
00761 SendByteICCParity(byte, inverse);
00762
00763
00764 Led1On();
00765 #if LCD_ENABLED
00766 if(lcdAvailable)
00767 {
00768 InitLCD();
00769 fprintf(stderr, "\n");
00770 WriteStringLCD(strDataSent, strlen(strDataSent));
00771 }
00772 #endif
00773 }
00774
00778 void SwitchLeds()
00779 {
00780 while(1)
00781 {
00782 _delay_ms(500);
00783 Led1On();
00784 Led2Off();
00785 _delay_ms(500);
00786 Led1Off();
00787 Led2On();
00788 }
00789 }
00790