/*! \fn guiMainLoop(void) * \brief Main user interface loop */ void guiMainLoop(void) { RET_TYPE touch_detect_result; uint8_t isScreenOnCopy; #ifdef HARDWARE_V1 return; #endif // Set led mask depending on our current screen switch(getCurrentScreen()) { case SCREEN_DEFAULT_NINSERTED : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; case SCREEN_DEFAULT_INSERTED_LCK : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; case SCREEN_DEFAULT_INSERTED_NLCK : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT; break; case SCREEN_DEFAULT_INSERTED_INVALID : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; case SCREEN_SETTINGS : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT; break; case SCREEN_MEMORY_MGMT : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; default: break; } // Make a copy of the screen on bool isScreenOnCopy = oledIsOn(); // Launch touch detection routine to check for interactions touch_detect_result = touchDetectionRoutine(currentLedMask); // No activity, switch off LEDs and activate prox detection if (hasTimerExpired(TIMER_LIGHT, TRUE) == TIMER_EXPIRED) { setPwmDc(0x0000); areLightsOn = FALSE; activateProxDetection(); } // No activity, switch off screen if (hasTimerExpired(TIMER_SCREEN, TRUE) == TIMER_EXPIRED) { guiDisplayGoingToSleep(); userViewDelay(); oledFlipBuffers(0,0); #ifndef HARDWARE_V1 oledOff(); #endif } // If the screen just got turned on, don't call the guiScreenLoop() function if ((touch_detect_result & TOUCH_PRESS_MASK) && (isScreenOnCopy != FALSE)) { guiScreenLoop(touch_detect_result); } }
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 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 guiMainLoop(void) * \brief Main user interface loop */ void guiMainLoop(void) { RET_TYPE input_interface_result; uint8_t screenSaverOnCopy; uint8_t isScreenOnCopy; #if defined(HARDWARE_OLIVIER_V1) // Set led mask depending on our current screen switch(getCurrentScreen()) { case SCREEN_DEFAULT_NINSERTED : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; case SCREEN_DEFAULT_INSERTED_LCK : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; case SCREEN_DEFAULT_INSERTED_NLCK : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT; break; case SCREEN_DEFAULT_INSERTED_INVALID : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; case SCREEN_SETTINGS : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT; break; case SCREEN_MEMORY_MGMT : currentLedMask = LED_MASK_LEFT|LED_MASK_RIGHT|LED_MASK_WHEEL; break; default: break; } #endif // Make a copy of the screen on & screensaver on bools screenSaverOnCopy = screenSaverOn; isScreenOnCopy = oledIsOn(); #if defined(HARDWARE_OLIVIER_V1) // Launch touch detection routine to check for interactions input_interface_result = touchDetectionRoutine(currentLedMask); #elif defined(MINI_VERSION) input_interface_result = miniGetWheelAction(FALSE, FALSE); #endif #if defined(HARDWARE_OLIVIER_V1) // No activity, switch off LEDs and activate prox detection if (hasTimerExpired(TIMER_LIGHT, TRUE) == TIMER_EXPIRED) { setPwmDc(0x0000); areLightsOn = FALSE; activateProxDetection(); } #endif // No activity, switch off screen if (hasTimerExpired(TIMER_SCREEN, TRUE) == TIMER_EXPIRED) { guiDisplayGoingToSleep(); userViewDelay(); if (getMooltipassParameterInEeprom(SCREENSAVER_PARAM) != FALSE) { screenSaverOn = TRUE; oledWriteInactiveBuffer(); oledClear(); oledDisplayOtherBuffer(); oledClear(); } else { oledDisplayOtherBuffer(); oledOff(); } } #if defined(HARDWARE_OLIVIER_V1) // If there was some activity and we are showing the screen saver if ((input_interface_result & TOUCH_PRESS_MASK) && (screenSaverOnCopy == TRUE)) { guiGetBackToCurrentScreen(); } // If the screen just got turned on, don't call the guiScreenLoop() function if ((input_interface_result & TOUCH_PRESS_MASK) && (((isScreenOnCopy != FALSE) && (screenSaverOnCopy == FALSE)) || (getCurrentScreen() == SCREEN_DEFAULT_INSERTED_LCK))) { guiScreenLoop(input_interface_result); } #elif defined(MINI_VERSION) // If there was some activity and we are showing the screen saver if ((input_interface_result != WHEEL_ACTION_NONE) && (screenSaverOnCopy == TRUE)) { guiGetBackToCurrentScreen(); } if ((input_interface_result != WHEEL_ACTION_NONE) && (((isScreenOnCopy != FALSE) && (screenSaverOnCopy == FALSE)) || (getCurrentScreen() == SCREEN_DEFAULT_INSERTED_LCK))) { guiScreenLoop(input_interface_result); } #endif }