/*! \fn displayInitForTest() * \brief Init OLED SCREEN per test */ void displayInitForTest(void) { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED oledClear(); oledSetXY(0,0); printf_P(PSTR("Flash Test")); oledSetXY(0,8); #endif #ifdef FLASH_TEST_DEBUG_OUTPUT_USB usbPrintf_P(PSTR("\n----Flash Test----\n")); #endif }
void afterTouchInitTests(void) { //#define TEST_TS #ifdef TEST_TS uint8_t temp_byte; uint16_t temp_uint = 0; RET_TYPE temp_ret_type = RETURN_RIGHT_PRESSED; activityDetectedRoutine(); oledWriteActiveBuffer(); activateProxDetection(); while(!(temp_ret_type & RETURN_LEFT_PRESSED)) { if (temp_ret_type != RETURN_NO_CHANGE) { oledSetXY(0,0); readDataFromTS(REG_AT42QT_SLIDER_POS, &temp_byte); printf("POS: %02X\r\n", temp_byte); readDataFromTS(REG_AT42QT_DET_STAT, &temp_byte); printf("DET STAT: %02X\r\n", temp_byte); readDataFromTS(REG_AT42QT_KEY_STAT1, &temp_byte); printf("DET1: %02X\r\n", temp_byte); readDataFromTS(REG_AT42QT_KEY_STAT2, &temp_byte); printf("DET2: %02X\r\n", temp_byte); printf("counter: %04X\r\n", temp_uint++); } temp_ret_type = touchDetectionRoutine(); } activateGuardKey(); launchCalibrationCycle(); while(1) { if (temp_ret_type != RETURN_NO_CHANGE) { oledSetXY(0,0); readDataFromTS(REG_AT42QT_SLIDER_POS, &temp_byte); printf("POS: %02X\r\n", temp_byte); readDataFromTS(REG_AT42QT_DET_STAT, &temp_byte); printf("DET STAT: %02X\r\n", temp_byte); readDataFromTS(REG_AT42QT_KEY_STAT1, &temp_byte); printf("DET1: %02X\r\n", temp_byte); readDataFromTS(REG_AT42QT_KEY_STAT2, &temp_byte); printf("DET2: %02X\r\n", temp_byte); printf("counter: %04X\r\n", temp_uint++); } temp_ret_type = touchDetectionRoutine(); } #endif }
/*! \fn displayFailed() * \brief Display FAILED Message */ void displayFailed(void) { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED oledSetXY(0,16); printf_P(PSTR("FAILED")); #endif #ifdef FLASH_TEST_DEBUG_OUTPUT_USB usbPrintf_P(PSTR("FAILED\n")); #endif }
void afterHadLogoDisplayTests(void) { //#define TEST_PWM #ifdef TEST_PWM uint8_t toto = 0; switchOnLeftButonLed(); switchOnRightButonLed(); switchOnTopLeftWheelLed(); switchOnTopRightWheelLed(); switchOnBotLeftWheelLed(); switchOnBotRightWheelLed(); oledWriteActiveBuffer(); while(1) { oledSetXY(2,0); printf("%02X", MAX_PWM_VAL >> toto); setPwmDc(MAX_PWM_VAL >> toto); _delay_ms(1000); if(toto++ == 11) toto = 0; } #endif //#define TEST_HID #ifdef TEST_HID uint8_t i; while(1) { if (getKeyboardLeds() & HID_CAPS_MASK) { usbPutstr("NOPE!\r\n"); while(getKeyboardLeds() & HID_CAPS_MASK) { usbKeyboardPress(KEY_CAPS_LOCK, 0); _delay_ms(30); } for(i = ' '; i < 0x7F; i++) { usbKeybPutChar(i); } usbKeybPutStr("\rBonjour oh grand dieu!\n"); } } #endif //#define TEST_PLUGIN #ifdef TEST_PLUGIN printf_P(PSTR("Plugin test\n")); oledFlipBuffers(OLED_SCROLL_UP,5); oledClear(); // clear inactive buffer oledWriteActiveBuffer(); #endif }
/*! \fn displayPassed() * \brief Display PASSED Message (with delay) */ void displayPassed(void) { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED oledSetXY(0,16); printf_P(PSTR("PASSED")); #endif #ifdef FLASH_TEST_DEBUG_OUTPUT_USB usbPrintf_P(PSTR("PASSED\n")); #endif timerBasedDelayMs(1000); }
/*! \fn displayRWCode(RET_TYPE ret) * \brief display Read/Write Return Code * \param ret return code */ void displayRWCode(RET_TYPE ret) { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED oledSetXY(0,24); #endif if(ret == RETURN_NO_MATCH) { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED printf_P(PSTR("NO MATCH")); #endif #ifdef FLASH_TEST_DEBUG_OUTPUT_USB usbPrintf_P(PSTR("NO MATCH\n")); #endif } else if(ret == RETURN_READ_ERR) { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED printf_P(PSTR("READ ERROR")); #endif #ifdef FLASH_TEST_DEBUG_OUTPUT_USB usbPrintf_P(PSTR("READ ERROR\n")); #endif } else if(ret == RETURN_WRITE_ERR) { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED printf_P(PSTR("WRITE ERROR")); #endif #ifdef FLASH_TEST_DEBUG_OUTPUT_USB usbPrintf_P(PSTR("WRITE ERROR\n")); #endif } else { #ifdef FLASH_TEST_DEBUG_OUTPUT_OLED printf_P(PSTR("BAD PARAM / UNKNOWN")); #endif #ifdef FLASH_TEST_DEBUG_OUTPUT_USB usbPrintf_P(PSTR("BAD PARAM / UNKNOWN\n")); #endif } }
/*! \fn guiDisplayPinOnPinEnteringScreen(uint8_t* current_pin, uint8_t selected_digit) * \brief Overwrite the digits on the current pin entering screen * \param current_pin Array containing the pin * \param selected_digit Currently selected digit */ void guiDisplayPinOnPinEnteringScreen(uint8_t* current_pin, uint8_t selected_digit) { oledFillXY(88, 31, 82, 19, 0x00); for (uint8_t i = 0; i < 4; i++) { oledSetXY(88+22*i, 25); if (i != selected_digit) { oledPutch('*'); } else { if (current_pin[i] >= 0x0A) { oledPutch(current_pin[i]+'A'-0x0A); } else { oledPutch(current_pin[i]+'0'); } } } }
/*! \fn main(void) * \brief Main function */ int main(void) { uint16_t current_bootkey_val = eeprom_read_word((uint16_t*)EEP_BOOTKEY_ADDR); RET_TYPE flash_init_result; RET_TYPE touch_init_result; RET_TYPE card_detect_ret; uint8_t fuse_ok = TRUE; // Disable JTAG to gain access to pins, set prescaler to 1 (fuses not set) #ifndef PRODUCTION_KICKSTARTER_SETUP disableJTAG(); CPU_PRESCALE(0); #endif // Check fuse settings: boot reset vector, 2k words, SPIEN, BOD 2.6V, programming & ver disabled if ((boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS) != 0xFF) || (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) != 0xD8) || (boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS) != 0xFB) || (boot_lock_fuse_bits_get(GET_LOCK_BITS) != 0xFC)) { fuse_ok = FALSE; } // Check if PB5 is low to start electrical test DDRB &= ~(1 << 5); PORTB |= (1 << 5); smallForLoopBasedDelay(); if (!(PINB & (1 << 5))) { // Test result, true by default uint8_t test_result = TRUE; // Leave flash nS off DDR_FLASH_nS |= (1 << PORTID_FLASH_nS); PORT_FLASH_nS |= (1 << PORTID_FLASH_nS); // Set PORTD as output, leave PORTID_OLED_SS high DDRD |= 0xFF; PORTD |= 0xFF; // All other pins are input by default, run our test for (uint8_t i = 0; i < 4; i++) { PORTD |= 0xFF; smallForLoopBasedDelay(); if (!(PINF & (0xC3)) || !(PINC & (1 << 6)) || !(PINE & (1 << 6)) || !(PINB & (1 << 4))) { test_result = FALSE; } PORTD &= (1 << PORTID_OLED_SS); smallForLoopBasedDelay(); if ((PINF & (0xC3)) || (PINC & (1 << 6)) || (PINE & (1 << 6)) || (PINB & (1 << 4))) { test_result = FALSE; } } // PB6 as test result output DDRB |= (1 << 6); // If test successful, light green LED if ((test_result == TRUE) && (fuse_ok == TRUE)) { PORTB |= (1 << 6); } else { PORTB &= ~(1 << 6); } while(1); } // This code will only be used for developers and beta testers #if !defined(PRODUCTION_SETUP) && !defined(PRODUCTION_KICKSTARTER_SETUP) // Check if we were reset and want to go to the bootloader if (current_bootkey_val == BOOTLOADER_BOOTKEY) { // Disable WDT wdt_reset(); wdt_clear_flag(); wdt_change_enable(); wdt_stop(); // Store correct bootkey eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY); // Jump to bootloader start_bootloader(); } // Check if there was a change in the mooltipass setting storage to reset the parameters to their correct values if (getMooltipassParameterInEeprom(USER_PARAM_INIT_KEY_PARAM) != USER_PARAM_CORRECT_INIT_KEY) { mooltipassParametersInit(); setMooltipassParameterInEeprom(USER_PARAM_INIT_KEY_PARAM, USER_PARAM_CORRECT_INIT_KEY); } #endif // First time initializations for Eeprom (first boot at production or flash layout changes for beta testers) if (current_bootkey_val != CORRECT_BOOTKEY) { // Erase Mooltipass parameters mooltipassParametersInit(); // Set bootloader password bool to FALSE eeprom_write_byte((uint8_t*)EEP_BOOT_PWD_SET, FALSE); } /* Check if a card is inserted in the Mooltipass to go to the bootloader */ #ifdef AVR_BOOTLOADER_PROGRAMMING /* Disable JTAG to get access to the pins */ disableJTAG(); /* Init SMC port */ initPortSMC(); /* Delay for detection */ smallForLoopBasedDelay(); #if defined(HARDWARE_V1) if (PIN_SC_DET & (1 << PORTID_SC_DET)) #elif defined(HARDWARE_OLIVIER_V1) if (!(PIN_SC_DET & (1 << PORTID_SC_DET))) #endif { uint16_t tempuint16; /* What follows is a copy from firstDetectFunctionSMC() */ /* Enable power to the card */ PORT_SC_POW &= ~(1 << PORTID_SC_POW); /* Default state: PGM to 0 and RST to 1 */ PORT_SC_PGM &= ~(1 << PORTID_SC_PGM); DDR_SC_PGM |= (1 << PORTID_SC_PGM); PORT_SC_RST |= (1 << PORTID_SC_RST); DDR_SC_RST |= (1 << PORTID_SC_RST); /* Activate SPI port */ PORT_SPI_NATIVE &= ~((1 << SCK_SPI_NATIVE) | (1 << MOSI_SPI_NATIVE)); DDRB |= (1 << SCK_SPI_NATIVE) | (1 << MOSI_SPI_NATIVE); setSPIModeSMC(); /* Let the card come online */ smallForLoopBasedDelay(); /* Check smart card FZ */ readFabricationZone((uint8_t*)&tempuint16); if ((swap16(tempuint16)) != SMARTCARD_FABRICATION_ZONE) { removeFunctionSMC(); start_bootloader(); } else { removeFunctionSMC(); } } #endif initPortSMC(); // Initialize smart card port initPwm(); // Initialize PWM controller initIRQ(); // Initialize interrupts powerSettlingDelay(); // Let the power settle initUsb(); // Initialize USB controller powerSettlingDelay(); // Let the USB 3.3V LDO rise initI2cPort(); // Initialize I2C interface rngInit(); // Initialize avrentropy library oledInitIOs(); // Initialize OLED input/outputs spiUsartBegin(SPI_RATE_8_MHZ); // Start USART SPI at 8MHz // If offline mode isn't enabled, wait for device to be enumerated if (getMooltipassParameterInEeprom(OFFLINE_MODE_PARAM) == FALSE) { while(!isUsbConfigured()); // Wait for host to set configuration } // Set correct timeout_enabled val mp_timeout_enabled = getMooltipassParameterInEeprom(LOCK_TIMEOUT_ENABLE_PARAM); // Launch the before flash initialization tests #ifdef TESTS_ENABLED beforeFlashInitTests(); #endif // Check if we can initialize the Flash memory flash_init_result = initFlash(); // Launch the after flash initialization tests #ifdef TESTS_ENABLED afterFlashInitTests(); #endif // Set up OLED now that USB is receiving full 500mA. oledBegin(FONT_DEFAULT); // First time initializations for Flash (first time power up at production) if (current_bootkey_val != CORRECT_BOOTKEY) { // Erase everything non graphic in flash eraseFlashUsersContents(); // Erase # of cards and # of users firstTimeUserHandlingInit(); } // Check if we can initialize the touch sensing element touch_init_result = initTouchSensing(); // Enable proximity detection #ifndef HARDWARE_V1 activateProxDetection(); #endif // Launch the after touch initialization tests #ifdef TESTS_ENABLED afterTouchInitTests(); #endif // Test procedure to check that all HW is working #if defined(PRODUCTION_SETUP) || defined(PRODUCTION_KICKSTARTER_SETUP) if (current_bootkey_val != CORRECT_BOOTKEY) { RET_TYPE temp_rettype; // Wait for USB host to upload bundle, which then sets USER_PARAM_INIT_KEY_PARAM //#ifdef PRODUCTION_KICKSTARTER_SETUP while(getMooltipassParameterInEeprom(USER_PARAM_INIT_KEY_PARAM) != 0xF1) { usbProcessIncoming(USB_CALLER_MAIN); } //#endif // Bundle uploaded, start the screen oledBegin(FONT_DEFAULT); oledWriteActiveBuffer(); oledSetXY(0,0); // LEDs ON, to check setPwmDc(MAX_PWM_VAL); switchOnButtonWheelLeds(); guiDisplayRawString(ID_STRING_TEST_LEDS_CH); // Check flash init if (flash_init_result != RETURN_OK) { guiDisplayRawString(ID_STRING_TEST_FLASH_PB); } // Check touch init if (touch_init_result != RETURN_OK) { guiDisplayRawString(ID_STRING_TEST_TOUCH_PB); } // Touch instructions guiDisplayRawString(ID_STRING_TEST_INST_TCH); // Check prox while(!(touchDetectionRoutine(0) & RETURN_PROX_DETECTION)); guiDisplayRawString(ID_STRING_TEST_DET); activateGuardKey(); // Check left while(!(touchDetectionRoutine(0) & RETURN_LEFT_PRESSED)); guiDisplayRawString(ID_STRING_TEST_LEFT); // Check wheel while(!(touchDetectionRoutine(0) & RETURN_WHEEL_PRESSED)); guiDisplayRawString(ID_STRING_TEST_WHEEL); // Check right while(!(touchDetectionRoutine(0) & RETURN_RIGHT_PRESSED)); guiDisplayRawString(ID_STRING_TEST_RIGHT); // Insert card guiDisplayRawString(ID_STRING_TEST_CARD_INS); while(isCardPlugged() != RETURN_JDETECT); temp_rettype = cardDetectedRoutine(); // Check card if (!((temp_rettype == RETURN_MOOLTIPASS_BLANK) || (temp_rettype == RETURN_MOOLTIPASS_USER))) { guiDisplayRawString(ID_STRING_TEST_CARD_PB); } // Display result uint8_t script_return = RETURN_OK; if ((flash_init_result == RETURN_OK) && (touch_init_result == RETURN_OK) && ((temp_rettype == RETURN_MOOLTIPASS_BLANK) || (temp_rettype == RETURN_MOOLTIPASS_USER))) { // Inform script of success usbSendMessage(CMD_FUNCTIONAL_TEST_RES, 1, &script_return); // Wait for password to be set while(eeprom_read_byte((uint8_t*)EEP_BOOT_PWD_SET) != BOOTLOADER_PWDOK_KEY) { usbProcessIncoming(USB_CALLER_MAIN); } // Display test result guiDisplayRawString(ID_STRING_TEST_OK); timerBasedDelayMs(3000); } else { // Set correct bool script_return = RETURN_NOK; // Display test result guiDisplayRawString(ID_STRING_TEST_NOK); // Inform script of failure usbSendMessage(CMD_FUNCTIONAL_TEST_RES, 1, &script_return); while(1) { usbProcessIncoming(USB_CALLER_MAIN); } } } #endif // Stop the Mooltipass if we can't communicate with the flash or the touch interface #if defined(HARDWARE_OLIVIER_V1) #ifdef PRODUCTION_KICKSTARTER_SETUP while ((flash_init_result != RETURN_OK) || (touch_init_result != RETURN_OK) || (fuse_ok != TRUE)); #else while ((flash_init_result != RETURN_OK) || (touch_init_result != RETURN_OK)); #endif #endif // First time initializations done.... write correct value in eeprom if (current_bootkey_val != CORRECT_BOOTKEY) { // Store correct bootkey eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY); } // Write inactive buffer & go to startup screen oledWriteInactiveBuffer(); guiSetCurrentScreen(SCREEN_DEFAULT_NINSERTED); guiGetBackToCurrentScreen(); // Launch the after HaD logo display tests #ifdef TESTS_ENABLED afterHadLogoDisplayTests(); #endif // Let's fade in the LEDs for (uint16_t i = 0; i < MAX_PWM_VAL; i++) { setPwmDc(i); timerBasedDelayMs(0); } activityDetectedRoutine(); launchCalibrationCycle(); touchClearCurrentDetections(); // Inhibit touch inputs for the first 3 seconds activateTimer(TIMER_TOUCH_INHIBIT, 3000); while (1) { // Process possible incoming USB packets usbProcessIncoming(USB_CALLER_MAIN); // Call GUI routine once the touch input inhibit timer is finished if (hasTimerExpired(TIMER_TOUCH_INHIBIT, FALSE) == TIMER_EXPIRED) { guiMainLoop(); } // Check if a card just got inserted / removed card_detect_ret = isCardPlugged(); // Do appropriate actions on smartcard insertion / removal if (card_detect_ret == RETURN_JDETECT) { // Light up the Mooltipass and call the dedicated function activityDetectedRoutine(); handleSmartcardInserted(); } else if (card_detect_ret == RETURN_JRELEASED) { // Light up the Mooltipass and call the dedicated function activityDetectedRoutine(); handleSmartcardRemoved(); // Set correct screen guiDisplayInformationOnScreen(ID_STRING_CARD_REMOVED); guiSetCurrentScreen(SCREEN_DEFAULT_NINSERTED); userViewDelay(); guiGetBackToCurrentScreen(); } // Two quick caps lock presses wakes up the device if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_EXPIRED) && (getKeyboardLeds() & HID_CAPS_MASK) && (wasCapsLockTimerArmed == FALSE)) { wasCapsLockTimerArmed = TRUE; activateTimer(TIMER_CAPS, CAPS_LOCK_DEL); } else if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_RUNNING) && !(getKeyboardLeds() & HID_CAPS_MASK)) { activityDetectedRoutine(); } else if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_EXPIRED) && !(getKeyboardLeds() & HID_CAPS_MASK)) { wasCapsLockTimerArmed = FALSE; } // If we have a timeout lock if ((mp_timeout_enabled == TRUE) && (hasTimerExpired(SLOW_TIMER_LOCKOUT, TRUE) == TIMER_EXPIRED)) { guiSetCurrentScreen(SCREEN_DEFAULT_INSERTED_LCK); guiGetBackToCurrentScreen(); handleSmartcardRemoved(); } } }
/*! \fn afterFlashInitTests(void) * \brief Test functions launched after flash init */ void afterFlashInitTests(void) { //#define TEST_NODE #ifdef TEST_NODE nodeTest(); // spin while(1); #endif //#define TEST_HID_AND_CDC #ifdef TEST_HID_AND_CDC //Show_String("Z",FALSE,2,0); //usbKeyboardPress(KEY_S, 0); while(1) { int n = usb_serial_getchar(); if (n >= 0) { usb_serial_putchar(n); oledSetXY(2,0); oledPutch((char)n); //usbKeyboardPress(n,0); } } #endif /* TEST_HID_AND_CDC */ //#define NESSIE_TEST_VECTORS #ifdef NESSIE_TEST_VECTORS while(1) { // msg into oled display oledSetXY(2,0); printf_P(PSTR("send s to start nessie test")); int input0 = usb_serial_getchar(); nessieOutput = &usb_serial_putchar; // do nessie test after sending s or S chars if (input0 == 's' || input0 == 'S') { nessieTest(1); nessieTest(2); nessieTest(3); nessieTest(4); nessieTest(5); nessieTest(6); nessieTest(7); nessieTest(8); } } #endif //#define CTR_TEST_VECTORS #ifdef CTR_TEST_VECTORS while(1) { // msg into oled display oledSetXY(2,0); printf_P(PSTR("send s to start CTR test")); int input1 = usb_serial_getchar(); ctrTestOutput = &usb_serial_putchar; // do ctr test after sending s or S chars if (input1 == 's' || input1 == 'S') { aes256CtrTest(); } } #endif //#define TEST_CTR_SPEED #ifdef TEST_CTR_SPEED // msg into oled display oledSetXY(2,0); usbPrintf_P(PSTR("CTR speed TEST with 1000 encryptions\n")); usbPrintf_P(PSTR("Time:")); usbPrintf_P(PSTR("%lu ms"), aes256CtrSpeedTest()); while(1); #endif //#define TEST_RNG #ifdef TEST_RNG while(1) { // init avrentropy library EntropyInit(); // msg into oled display oledSetXY(2,0); printf_P(PSTR("send s to start entropy")); int input2 = usb_serial_getchar(); uint32_t randomNumCtr; // do nessie test after sending s or S chars if (input2 == 's' || input2 == 'S') { while(EntropyAvailable() < 2); EntropyRandom8(); usb_serial_putchar(EntropyBytesAvailable()); for(randomNumCtr=0; randomNumCtr<25; randomNumCtr++) { usb_serial_putchar(EntropyRandom8()); } } } #endif }