Пример #1
0
/*! \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);
    }   
}
Пример #2
0
bool
CEventQueue::getEvent(CEvent& event, double timeout)
{
	CStopwatch timer(true);
retry:
	// if no events are waiting then handle timers and then wait
	while (m_buffer->isEmpty()) {
		// handle timers first
		if (hasTimerExpired(event)) {
			return true;
		}

		// get time remaining in timeout
		double timeLeft = timeout - timer.getTime();
		if (timeout >= 0.0 && timeLeft <= 0.0) {
			return false;
		}

		// get time until next timer expires.  if there is a timer
		// and it'll expire before the client's timeout then use
		// that duration for our timeout instead.
		double timerTimeout = getNextTimerTimeout();
		if (timeout < 0.0 || (timerTimeout >= 0.0 && timerTimeout < timeLeft)) {
			timeLeft = timerTimeout;
		}

		// wait for an event
		m_buffer->waitForEvent(timeLeft);
	}

	// get the event
	UInt32 dataID;
	IEventQueueBuffer::Type type = m_buffer->getEvent(event, dataID);
	switch (type) {
	case IEventQueueBuffer::kNone:
		if (timeout < 0.0 || timeout <= timer.getTime()) {
			// don't want to fail if client isn't expecting that
			// so if getEvent() fails with an infinite timeout
			// then just try getting another event.
			goto retry;
		}
		return false;

	case IEventQueueBuffer::kSystem:
		return true;

	case IEventQueueBuffer::kUser:
		{
			CArchMutexLock lock(m_mutex);
			event = removeEvent(dataID);
			return true;
		}

	default:
		assert(0 && "invalid event type");
		return false;
	}
}
Пример #3
0
/*! \fn     getTouchedPositionAnswer(uint8_t led_mask)
*   \brief  Use the capacitive interface to get quarter position
*   \param  led_mask    Led mask for the touchdetection routine
*   \return Number between 0 and 5 for valid pos, -1 otherwise
*/
int8_t getTouchedPositionAnswer(uint8_t led_mask)
{
    #ifdef HARDWARE_V1
        _delay_ms(2000);
    #endif
    #if defined(ALWAYS_ACCEPT_REQUESTS) || defined(HARDWARE_V1)
        // First quarter is discarded, it means we want yes or no!
        if (led_mask & LED_MASK_WHEEL_TLEFT)
        {
            return TOUCHPOS_RIGHT;
        }
        else
        {
            return TOUCHPOS_WHEEL_TLEFT;
        }
    #endif

    RET_TYPE touch_detect_result;
    
    // Switch on lights
    activityDetectedRoutine();
    
    // Clear possible remaining detection
    touchDetectionRoutine(led_mask);
    touchWaitForWheelReleased();
    touchClearCurrentDetections();
    
    // Wait for a touch press, delay stored in eeprom (1024 is quite close to 1000 ;-) )
    activateTimer(TIMER_USERINT, ((uint16_t)controlEepromParameter(getMooltipassParameterInEeprom(USER_INTER_TIMEOUT_PARAM), MIN_USER_INTER_DEL/1000, MAX_USER_INTER_DEL/1000)) << 10);
    do
    {
        // User interaction timeout or smartcard removed
        if ((hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED) || (isSmartCardAbsent() == RETURN_OK))
        {
            return -1;
        }
        touch_detect_result = touchDetectionRoutine(led_mask) & TOUCH_PRESS_MASK;
    }
    while (!touch_detect_result);
    
    // Did the user press one of the two touch buttons?
    if (touch_detect_result & RETURN_LEFT_PRESSED)
    {
        return TOUCHPOS_LEFT;
    }
    else if (touch_detect_result & RETURN_RIGHT_PRESSED)
    {
        return TOUCHPOS_RIGHT;
    }
    else
    {
        return (int8_t)getWheelTouchDetectionQuarter();
    }
}
Пример #4
0
/*! \fn     getYesNoAnswerInput(uint8_t blocking)
*   \brief  Use the input interface to get user input
*   \param  blocking    Boolean to know if we should wait for input or timeout
*   \note   In case of a non blocking call, caller must call activityDetectedRoutine() & miniWheelClearDetections()
*   \return see mini_input_yes_no_ret_t
*/
RET_TYPE getYesNoAnswerInput(uint8_t blocking)
{
    #if defined(ALWAYS_ACCEPT_REQUESTS)
        return MINI_INPUT_RET_YES;
    #endif

    uint8_t incomingData[RAWHID_TX_SIZE];
    RET_TYPE detect_result;
    
    if (blocking == TRUE)
    {
        // Switch on lights
        activityDetectedRoutine();
        
        // Clear possible remaining detection
        miniWheelClearDetections();
    }
    
    // Wait for a touch press
    do
    {
        // User interaction timeout or smartcard removed
        if ((hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED) || (isSmartCardAbsent() == RETURN_OK))
        {
            return MINI_INPUT_RET_TIMEOUT;
        }
        
        // Read usb comms as the plugin could ask to cancel the request
        if ((getMooltipassParameterInEeprom(USER_REQ_CANCEL_PARAM) != FALSE) && (usbRawHidRecv(incomingData) == RETURN_COM_TRANSF_OK))
        {
            if (incomingData[HID_TYPE_FIELD] == CMD_CANCEL_REQUEST)
            {
                // Request canceled
                return MINI_INPUT_RET_TIMEOUT;
            }
            else
            {
                // Another packet (that shouldn't be sent!), ask to retry later...
                usbSendMessage(CMD_PLEASE_RETRY, 0, incomingData);
            }
        }
        
        // Check if something has been pressed
        detect_result = miniGetWheelAction(FALSE, TRUE);
        if (detect_result == WHEEL_ACTION_SHORT_CLICK)
        {
            return MINI_INPUT_RET_YES;
        }
    }
    while(blocking != FALSE);
    
    // Return MINI_INPUT_RET_NONE if nothing was pressed and no timeout occurred
    return MINI_INPUT_RET_NONE;
}    
Пример #5
0
/*! \fn     usbKeyboardSend(void)
*   \brief  Send the contents of keyboard_keys and keyboard_modifier_keys
*   \return If we managed to send the keyboard keys
*/
RET_TYPE usbKeyboardSend(void)
{
    uint8_t i, intr_state;

    if (!usb_configuration)
    {
        return RETURN_COM_NOK;
    }
    intr_state = SREG;
    cli();
    UENUM = KEYBOARD_ENDPOINT;
    // Activate timeout timer
    activateTimer(TIMER_WAIT_FUNCTS, USB_WRITE_TIMEOUT);
    while (1)
    {
        // are we ready to transmit?
        if (UEINTX & (1<<RWAL))
        {
            break;
        }
        SREG = intr_state;
        // has the USB gone offline?
        if (!usb_configuration)
        {
            return RETURN_COM_NOK;
        }
        // have we waited too long?
        if (hasTimerExpired(TIMER_WAIT_FUNCTS, TRUE) == TIMER_EXPIRED)
        {
            return RETURN_COM_TIMEOUT;
        }
        // get ready to try checking again
        intr_state = SREG;
        cli();
        UENUM = KEYBOARD_ENDPOINT;
    }
    UEDATX = keyboard_modifier_keys;
    UEDATX = 0;
    for (i=0; i<6; i++)
    {
        UEDATX = keyboard_keys[i];
    }
    UEINTX = 0x3A;
    keyboard_idle_count = 0;
    SREG = intr_state;
    return RETURN_COM_TRANSF_OK;
}
/*! \fn     guiDisplayInsertSmartCardScreenAndWait(void)
*   \brief  Ask for the user to insert his smart card
*   \return RETURN_OK if the user inserted and unlocked his smartcard
*/
RET_TYPE guiDisplayInsertSmartCardScreenAndWait(void)
{
    RET_TYPE card_detect_ret = RETURN_JRELEASED;
        
    //#define KEYBOARD_LAYOUT_TEST
    #ifdef KEYBOARD_LAYOUT_TEST
    for (uint8_t i = ' '; i <= '~'; i++)
    {
        usbKeybPutChar(i);
        usbKeybPutChar(i);
    }
    //setMooltipassParameterInEeprom(KEYBOARD_LAYOUT_PARAM, getMooltipassParameterInEeprom(KEYBOARD_LAYOUT_PARAM)+1);
    //if (getMooltipassParameterInEeprom(KEYBOARD_LAYOUT_PARAM) > LAST_KEYB_LUT)
    //{
    //    setMooltipassParameterInEeprom(KEYBOARD_LAYOUT_PARAM, FIRST_KEYB_LUT);
    //}        
    #endif
    
    // Switch on lights
    activityDetectedRoutine();

    // Draw insert bitmap
    oledClear();
    oledBitmapDrawFlash(0, 0, BITMAP_INSERT, 0);
    oledFlipBuffers(0,0);
    
    // Wait for either timeout or for the user to insert his smartcard
    while ((hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_RUNNING) && (card_detect_ret != RETURN_JDETECT))
    {
        card_detect_ret = isCardPlugged();
        touchDetectionRoutine(0);
    }
    
    // If the user didn't insert his smart card
    if (card_detect_ret != RETURN_JDETECT)
    {
        // Get back to other screen
        guiGetBackToCurrentScreen();
        return RETURN_NOK;
    }
    else
    {
        return handleSmartcardInserted();
    }
}
Пример #7
0
/*! \fn     usbRawHidRecv(uint8_t *buffer, uint8_t timeout)
*   \brief  Receive a packet, with timeout
*   \param  buffer    Pointer to the buffer to store received data
*   \return RETURN_COM_TRANSF_OK or RETURN_COM_NOK or RETURN_COM_TIMEOUT
*/
RET_TYPE usbRawHidRecv(uint8_t *buffer)
{
    uint8_t intr_state;
    uint8_t i = 0;

    // if we're not online (enumerated and configured), error
    if (!usb_configuration)
    {
        return RETURN_COM_NOK;
    }
    intr_state = SREG;
    cli();
    // Activate timeout timer
    activateTimer(TIMER_WAIT_FUNCTS, USB_READ_TIMEOUT);
    UENUM = RAWHID_RX_ENDPOINT;
    // wait for data to be available in the FIFO
    while (1)
    {
        if (UEINTX & (1<<RWAL))
        {
            break;
        }
        SREG = intr_state;
        if (hasTimerExpired(TIMER_WAIT_FUNCTS, TRUE) == TIMER_EXPIRED)
        {
            return RETURN_COM_TIMEOUT;
        }
        if (!usb_configuration)
        {
            return RETURN_COM_NOK;
        }
        intr_state = SREG;
        cli();
        UENUM = RAWHID_RX_ENDPOINT;
    }
    for(i = 0; i < RAWHID_RX_SIZE; i++)
    {
        *buffer++ = UEDATX;
    }
    // release the buffer
    UEINTX = 0x6B;
    SREG = intr_state;
    return RETURN_COM_TRANSF_OK;
}
Пример #8
0
/*! \fn     guiGetPinFromUser(volatile uint16_t* pin_code, uint8_t stringID)
*   \brief  Ask the user to enter a PIN
*   \param  pin_code    Pointer to where to store the pin code
*   \param  stringID    String ID
*   \return If the user approved the request
*/
RET_TYPE guiGetPinFromUser(volatile uint16_t* pin_code, uint8_t stringID)
{
    // If we don't need a pin code, send default one
    #if defined(NO_PIN_CODE_REQUIRED) || defined(HARDWARE_V1) || defined(V2_DEVELOPERS_BOTPCB_BOOTLOADER_SETUP)
        *pin_code = SMARTCARD_DEFAULT_PIN;
        return RETURN_OK;
    #endif
    
    RET_TYPE ret_val = RETURN_NOK;
    uint8_t selected_digit = 0;
    uint8_t finished = FALSE;
    uint8_t current_pin[4];
    RET_TYPE temp_rettype;
    int8_t temp_int8;
    
    // Set current pin to 0000
    memset((void*)current_pin, 0, 4);
    
    // Draw pin entering bitmap
    oledClear();
    oledBitmapDrawFlash(0, 0, BITMAP_YES_NO, 0);
    oledBitmapDrawFlash(83, 51, BITMAP_PIN_LINES, 0);
    oledBitmapDrawFlash(238, 23, BITMAP_RIGHT_ARROW, 0);
    oledPutstrXY(0, 0, OLED_CENTRE, readStoredStringToBuffer(stringID));
    oledDisplayOtherBuffer();
    oledSetFont(FONT_PROFONT_24);
    oledWriteActiveBuffer();
    
    // Display current pin on screen
    guiDisplayPinOnPinEnteringScreen(current_pin, selected_digit);
    
    // While the user hasn't entered his pin
    while(!finished)
    {
        // Still process the USB commands
        usbProcessIncoming(USB_CALLER_PIN);
        // Detect key touches
        temp_rettype = touchDetectionRoutine(0);
        // Send it to the touch wheel interface logic
        temp_int8 = touchWheelIntefaceLogic(temp_rettype);
        
        // Position increment / decrement
        if (temp_int8 != 0)
        {
            if ((current_pin[selected_digit] == 0x0F) && (temp_int8 == 1))
            {
                current_pin[selected_digit] = 0xFF;
            }
            else if ((current_pin[selected_digit] == 0) && (temp_int8 == -1))
            {
                current_pin[selected_digit] = 0x10;
            }
            current_pin[selected_digit] += temp_int8;
            guiDisplayPinOnPinEnteringScreen(current_pin, selected_digit);
        }
        
        if ((isSmartCardAbsent() == RETURN_OK) || (hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED))
        {
            // Smartcard removed, no reason to continue
            ret_val = RETURN_NOK;
            finished = TRUE;
        }
        if (temp_rettype & RETURN_LEFT_PRESSED)
        {
            if (selected_digit == 1)
            {
                oledFillXY(0, 23, 18, 18, 0x00);
                oledBitmapDrawFlash(0, 24, BITMAP_CROSS, 0);
            }
            if (selected_digit > 0)
            {
                // When going back set pin digit to 0
                current_pin[selected_digit] = 0;
                current_pin[--selected_digit] = 0;
            }
            else
            {
                ret_val = RETURN_NOK;
                finished = TRUE;
            }
            guiDisplayPinOnPinEnteringScreen(current_pin, selected_digit);
            oledBitmapDrawFlash(238, 23, BITMAP_RIGHT_ARROW, 0);
        }
        else if (temp_rettype & RETURN_RIGHT_PRESSED)
        {
            if (selected_digit == 2)
            {
                oledFillXY(238, 23, 18, 18, 0x00);
                oledBitmapDrawFlash(240, 24, BITMAP_TICK, 0);
            }
            if (selected_digit < 3)
            {
                selected_digit++;
            }
            else
            {
                ret_val = RETURN_OK;
                finished = TRUE;
            }
            guiDisplayPinOnPinEnteringScreen(current_pin, selected_digit);
            oledBitmapDrawFlash(0, 23, BITMAP_LEFT_ARROW, 0);
        }
    }
    
    // Reset default font
    oledSetFont(FONT_DEFAULT);
    oledWriteInactiveBuffer();
    
    // Store the pin
    *pin_code = (uint16_t)(((uint16_t)(current_pin[0]) << 12) | (((uint16_t)current_pin[1]) << 8) | (current_pin[2] << 4) | current_pin[3]);
    
    // Set current pin to 0000
    memset((void*)current_pin, 0, 4);
    
    // Prevent touches until the user lifts his finger
    touchInhibitUntilRelease();
    
    // Return success status
    return ret_val;
}
Пример #9
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     loginSelectionScreen(void)
*   \brief  Screen displayed to let the user choose/find a login
*   \return Valid child node address or 0 otherwise
*/
uint16_t loginSelectionScreen(void)
{
    char currentText[SEARCHTEXT_MAX_LENGTH+1];
    uint8_t displayRefreshNeeded = TRUE;
    uint16_t ret_val = NODE_ADDR_NULL;
    uint8_t wasWheelReleased = TRUE;
    uint16_t tempParentAddresses[5];
    uint8_t currentStringIndex = 0;
    uint8_t nbMatchedParents= 0;
    uint8_t finished = FALSE;
    RET_TYPE temp_rettype;
    uint8_t led_mask = 0;
    int8_t temp_int8;
    
    // Set current text to a
    last_matching_parent_addr = NODE_ADDR_NULL;
    last_matching_parent_number = 0;
    memcpy(currentText, "a\x00\x00\x00\x00", sizeof(currentText));
    
    // Draw bitmap, display it and write active buffer
    oledBitmapDrawFlash(0, 0, BITMAP_LOGIN_FIND, 0);
    oledDisplayOtherBuffer();
    oledWriteActiveBuffer();
    
    // While the user hasn't chosen a credential
    while(!finished)
    {
        if (displayRefreshNeeded == TRUE)
        {
            nbMatchedParents = displayCurrentSearchLoginTexts(currentText, tempParentAddresses, currentStringIndex);
            displayRefreshNeeded = FALSE;
            
            // Light only the available choices and right arrow
            led_mask = 0;
            for (temp_int8 = nbMatchedParents; temp_int8 < 5; temp_int8++)
            {
                led_mask |= (1 << temp_int8);
            }
        }
        
        // Detect key touches
        temp_rettype = touchDetectionRoutine(led_mask);
        
        // Algo to differentiate a tap from a scroll
        if ((temp_rettype & RETURN_WHEEL_PRESSED) && (wasWheelReleased == TRUE))
        {
            // We use the timer dedicated to touch inhibit for min
            activateTimer(TIMER_TOUCH_INHIBIT, TAP_MIN_DEL);
            // We use the timer dedicated to caps detect for max
            activateTimer(TIMER_CAPS, TAP_MAX_DEL);
            // This works because we use the same clearing flags 
            wasWheelReleased = FALSE;
        }
        else if (temp_rettype & RETURN_WHEEL_RELEASED)
        {
            // Check if it's a tap and that the selected domain is valid
            if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_RUNNING) && (hasTimerExpired(TIMER_TOUCH_INHIBIT, FALSE) == TIMER_EXPIRED) && (getWheelTouchDetectionQuarter() < nbMatchedParents))
            {
                ret_val = tempParentAddresses[getWheelTouchDetectionQuarter()];
                finished = TRUE;
            }
            wasWheelReleased = TRUE;
        }
        
        // Send it to the touch wheel interface logic
        temp_int8 = touchWheelIntefaceLogic(temp_rettype);

        // Position increment / decrement
        if (temp_int8 != 0)
        {
            if ((currentText[currentStringIndex] == 0x7A) && (temp_int8 == 1))
            {
                // z->0 wrap
                currentText[currentStringIndex] = 0x2F;
            }
            if ((currentText[currentStringIndex] == 0x39) && (temp_int8 == 1))
            {
                // 9->a wrap
                currentText[currentStringIndex] = 0x60;
            }
            else if ((currentText[currentStringIndex] == 0x30) && (temp_int8 == -1))
            {
                // 0->z wrap
                currentText[currentStringIndex] = 0x7B;
            }
            else if ((currentText[currentStringIndex] == 0x61) && (temp_int8 == -1))
            {
                // a->9 wrap
                currentText[currentStringIndex] = 0x3A;
            }
            currentText[currentStringIndex] += temp_int8;
            displayRefreshNeeded = TRUE;
        }
        
        if ((isSmartCardAbsent() == RETURN_OK) || (hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED))
        {
            // Smartcard removed or no interaction for a while
            finished = TRUE;
        }
        else if (temp_rettype & RETURN_LEFT_PRESSED)
        {
            // Change search index
            if (currentStringIndex > 0)
            {
                currentText[currentStringIndex--] = 0;
                displayRefreshNeeded = TRUE;
            } 
            else
            {
                finished = TRUE;
            }
        }
        else if ((temp_rettype & RETURN_RIGHT_PRESSED) && (nbMatchedParents > 4))
        {
            // Change search index only if we need to...
            currentText[++currentStringIndex] = 'a';
            displayRefreshNeeded = TRUE;
        }
    }
    
    // Set inactive buffer write by default
    oledWriteInactiveBuffer();
    
    return ret_val;
}    
Пример #11
0
/*! \fn     guiAskForConfirmation(const char* string)
*   \brief  Ask for user confirmation for different things
*   \param  nb_args     Number of text lines (must be either 1 2 or 3/4 (depending on the MP version))
*   \param  text_object Pointer to the text object if more than 1 line, pointer to the string if not
*   \return User confirmation or not
*/
RET_TYPE guiAskForConfirmation(uint8_t nb_args, confirmationText_t* text_object)
{
    uint8_t flash_flag_set = FALSE;
    uint8_t flash_flag = FALSE;
    uint8_t flash_sm = 0;

    // LED animation
    #ifdef LEDS_ENABLED_MINI
        miniLedsSetAnimation(ANIM_PULSE_UP_RAMP_DOWN);
    #endif
    
    // Check if we want to flash the screen
    if ((nb_args & 0xF0) != 0)
    {
        flash_flag_set = TRUE;
        nb_args = nb_args & 0x0F;
        // Check that the user didn't disable it
        if (getMooltipassParameterInEeprom(FLASH_SCREEN_PARAM) != FALSE)
        {
            flash_flag = TRUE;
        }
    }

    // Variables for scrolling
    uint8_t string_y_indexes[3];
    uint8_t string_extra_chars[3];
    uint8_t string_offset_cntrs[3] = {0,0,0};
    // Display variables
    uint8_t approve_selected = TRUE;
        
    // Draw asking bitmap
    miniOledClearFrameBuffer();
    miniOledSetMaxTextY(SSD1305_OLED_WIDTH-15);
    miniOledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_APPROVE, 0);
        
    // Display lines. 
    // Note: line are truncated at the miniOled driver level when miniOledTextWritingYIncrement is set to FALSE (default)
    if (nb_args == 1)
    {
        miniOledPutCenteredString(THREE_LINE_TEXT_SECOND_POS, (char*)text_object);
    }
    else if (nb_args == 2)
    {
        string_y_indexes[0] = TWO_LINE_TEXT_FIRST_POS;
        string_y_indexes[1] = TWO_LINE_TEXT_SECOND_POS;
    }
    else
    {
        string_y_indexes[0] = THREE_LINE_TEXT_FIRST_POS;
        string_y_indexes[1] = THREE_LINE_TEXT_SECOND_POS;
        string_y_indexes[2] = THREE_LINE_TEXT_THIRD_POS; 
    }
        
    // For loop to display lines when there is more than one arg
    if (nb_args > 1)
    {
        for (uint8_t i = 0; i < nb_args; i++)
        {
            string_extra_chars[i] = strlen(text_object->lines[i]) - miniOledPutCenteredString(string_y_indexes[i], text_object->lines[i]);
        }
    }
        
    miniOledFlushEntireBufferToDisplay();
    miniOledResetMaxTextY();
    
    // Wait for user input
    RET_TYPE input_answer = MINI_INPUT_RET_NONE;
    RET_TYPE detect_result;
        
    // Switch on lights
    activityDetectedRoutine();
        
    // Clear possible remaining detection
    miniWheelClearDetections();
        
    // Arm timer for scrolling (caps timer that isn't relevant here)
    activateTimer(TIMER_CAPS, SCROLLING_DEL);

    // Arm timer for flashing
    activateTimer(TIMER_FLASHING, 500);
        
    // Loop while no timeout occurs or no button is pressed
    while (input_answer == MINI_INPUT_RET_NONE)
    {
        // User interaction timeout or smartcard removed
        if ((hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED) || (isSmartCardAbsent() == RETURN_OK))
        {
            input_answer = MINI_INPUT_RET_TIMEOUT;
        }
            
        // Read usb comms as the plugin could ask to cancel the request
        if (usbCancelRequestReceived() == RETURN_OK)
        {
            input_answer = MINI_INPUT_RET_TIMEOUT;
        }

        // Screen flashing logic
        if ((hasTimerExpired(TIMER_FLASHING, TRUE) == TIMER_EXPIRED) && (flash_flag == TRUE) && (flash_sm < 4))
        {
            // Look at the flash_sm LSb to know what is the display state
            if ((flash_sm++ & 0x01) != 0x00)
            {
                miniOledNormalDisplay();
            } 
            else
            {
                miniOledInvertedDisplay();
            }
            // Re-arm timer
            activateTimer(TIMER_FLASHING, 500);
        }
            
        // Check if something has been pressed
        detect_result = miniGetWheelAction(FALSE, TRUE);
        if (detect_result == WHEEL_ACTION_SHORT_CLICK)
        {
            input_answer = MINI_INPUT_RET_YES;
        }
        else if (detect_result == WHEEL_ACTION_LONG_CLICK)
        {
            input_answer = MINI_INPUT_RET_BACK;
        }

        // Knock to approve
        #if defined(HARDWARE_MINI_CLICK_V2)
        if ((scanAndGetDoubleZTap(FALSE) == ACC_RET_KNOCK) && (flash_flag_set != FALSE))
        {
            input_answer = MINI_INPUT_RET_YES;
        }
        #else
        (void)flash_flag_set;
        #endif
            
        // Text scrolling
        if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_EXPIRED) && (nb_args > 1))
        {
            miniOledClearFrameBuffer();
            activateTimer(TIMER_CAPS, SCROLLING_DEL);
            miniOledSetMaxTextY(SSD1305_OLED_WIDTH-15);
            if(approve_selected == FALSE)
            {
                miniOledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_DENY, 0);
            }
            else
            {
                miniOledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_APPROVE, 0);
            }

            for (uint8_t i = 0; i < nb_args; i++)
            {
                if (string_extra_chars[i] > 0)
                {
                    miniOledPutCenteredString(string_y_indexes[i], (text_object->lines[i]) + string_offset_cntrs[i]);
                        
                    if (string_offset_cntrs[i]++ == string_extra_chars[i])
                    {
                        string_offset_cntrs[i] = 0;
                    }
                }
                else
                {
                    miniOledPutCenteredString(string_y_indexes[i], text_object->lines[i]);
                }
            }
            miniOledFlushEntireBufferToDisplay();
            miniOledResetMaxTextY();
        }

        // Approve / deny display change
        if (getWheelCurrentIncrement() != 0)
        {
            if(approve_selected == FALSE)
            {
                miniOledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_APPROVE, 0);
            }
            else
            {
                miniOledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_DENY, 0);
            }
            approve_selected = !approve_selected;
            miniOledFlushEntireBufferToDisplay();
        }
    } 
    
    // In case display was inverted, set it normally
    miniOledNormalDisplay();  
    
    if ((input_answer == MINI_INPUT_RET_YES) && (approve_selected != FALSE))
    {
        // LED animation
        #ifdef LEDS_ENABLED_MINI
            miniLedsSetAnimation(ANIM_NONE);
        #endif
        return RETURN_OK;
    }
    else if (input_answer == MINI_INPUT_RET_BACK)
    {
        // LED animation
        #ifdef LEDS_ENABLED_MINI
            miniLedsSetAnimation(ANIM_NONE);
        #endif
        return RETURN_BACK;
    }
    else
    {
        // LED animation
        #ifdef LEDS_ENABLED_MINI
            miniLedsSetAnimation(ANIM_NONE);
        #endif
        return RETURN_NOK;
    }
}
Пример #12
0
/*! \fn     guiAskForConfirmation(const char* string)
*   \brief  Ask for user confirmation for different things
*   \param  nb_args     Number of text lines (must be either 1 2 or 3/4 (depending on the MP version))
*   \param  text_object Pointer to the text object if more than 1 line, pointer to the string if not
*   \return User confirmation or not
*/
RET_TYPE guiAskForConfirmation(uint8_t nb_args, confirmationText_t* text_object)
{    
    uint8_t flash_flag = FALSE;
    
    // Check if we want to flash the screen
    if ((nb_args & 0xF0) != 0)
    {
        nb_args = nb_args & 0x0F;
        // Check that the user didn't disable it
        if (getMooltipassParameterInEeprom(FLASH_SCREEN_PARAM) != FALSE)
        {
            flash_flag = TRUE;
        }
    }
    
    #if defined(HARDWARE_OLIVIER_V1)
        // Temp string for truncating
        char string_tbd[31];
        string_tbd[30] = 0;
        
        // Draw asking bitmap
        oledClear();
        oledBitmapDrawFlash(0, 0, BITMAP_YES_NO_INT_L, 0);
        oledBitmapDrawFlash(222, 0, BITMAP_YES_NO_INT_R, 0);
    
        // If more than one line
        if (nb_args == 1)
        {
            // Yeah, that's a bit dirty
            oledPutstrXY(0, 24, OLED_CENTRE, (char*)text_object);
        }
        else
        {
            while (nb_args--)
            {
                // Truncate and then display string
                memcpy(string_tbd, text_object->lines[nb_args], 30);
                oledPutstrXY(0, 2 + (nb_args << 4), OLED_CENTRE, string_tbd);
            }
        }
    
        // Display result
        oledDisplayOtherBuffer();
    #elif defined(MINI_VERSION)
        // Variables for scrolling
        uint8_t string_y_indexes[3];
        uint8_t string_extra_chars[3];
        uint8_t string_offset_cntrs[3] = {0,0,0};
        // Display variables
        uint8_t approve_selected = TRUE;
        
        // Draw asking bitmap
        oledClear();
        miniOledSetMaxTextY(SSD1305_OLED_WIDTH-15);
        oledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_APPROVE, 0);
        
        // Display lines. 
        // Note: line are truncated at the oled driver level when miniOledTextWritingYIncrement is set to FALSE
        if (nb_args == 1)
        {
            miniOledPutCenteredString(THREE_LINE_TEXT_SECOND_POS, (char*)text_object);
        }
        else if (nb_args == 2)
        {
            string_y_indexes[0] = TWO_LINE_TEXT_FIRST_POS;
            string_y_indexes[1] = TWO_LINE_TEXT_SECOND_POS;
        }
        else
        {
            string_y_indexes[0] = THREE_LINE_TEXT_FIRST_POS;
            string_y_indexes[1] = THREE_LINE_TEXT_SECOND_POS;
            string_y_indexes[2] = THREE_LINE_TEXT_THIRD_POS; 
        }
        
        // For loop to display lines when there is more than one arg
        if (nb_args > 1)
        {
            for (uint8_t i = 0; i < nb_args; i++)
            {
                string_extra_chars[i] = strlen(text_object->lines[i]) - miniOledPutCenteredString(string_y_indexes[i], text_object->lines[i]);
            }
        }
        
        miniOledFlushEntireBufferToDisplay();
        miniOledResetMaxTextY();
    #endif

    // In case the display inverted, set it correctly
    if (flash_flag == TRUE)
    {
        activityDetectedRoutine();
        oledInvertedDisplay();
        timerBased500MsDelay();
        oledNormalDisplay();
        timerBased500MsDelay();
        oledInvertedDisplay();
        timerBased500MsDelay();
        oledNormalDisplay();
    }
    
    // Wait for user input
    #if defined(HARDWARE_OLIVIER_V1)
        if(getTouchedPositionAnswer(LED_MASK_WHEEL) == TOUCHPOS_RIGHT)
        {
            return RETURN_OK;
        }
        else
        {
            return RETURN_NOK;
        }
    #elif defined(MINI_VERSION)
        RET_TYPE input_answer = MINI_INPUT_RET_NONE;
        
        // Switch on lights
        activityDetectedRoutine();
        
        // Clear possible remaining detection
        miniWheelClearDetections();
        
        // Arm timer for scrolling (caps timer that isn't relevant here)
        activateTimer(TIMER_CAPS, SCROLLING_DEL);
        
        // Loop while no timeout occurs or no button is pressed
        while (input_answer == MINI_INPUT_RET_NONE)
        {
            input_answer = getYesNoAnswerInput(FALSE);
            
            // Text scrolling
            if ((hasTimerExpired(TIMER_CAPS, TRUE) == TIMER_EXPIRED) && (nb_args > 1))
            {
                miniOledDrawRectangle(0, 0, SSD1305_OLED_WIDTH-15, SSD1305_OLED_HEIGHT, FALSE);
                activateTimer(TIMER_CAPS, SCROLLING_DEL);
                miniOledSetMaxTextY(SSD1305_OLED_WIDTH-15);
                for (uint8_t i = 0; i < nb_args; i++)
                {
                    if (string_extra_chars[i] > 0)
                    {
                        miniOledPutCenteredString(string_y_indexes[i], (text_object->lines[i]) + string_offset_cntrs[i]);
                        
                        if (string_offset_cntrs[i]++ == string_extra_chars[i])
                        {
                            string_offset_cntrs[i] = 0;
                        }
                    }
                    else
                    {
                        miniOledPutCenteredString(string_y_indexes[i], text_object->lines[i]);
                    }
                }
                miniOledFlushEntireBufferToDisplay();
                miniOledResetMaxTextY();
            }

            // Approve / deny display change
            if (getWheelCurrentIncrement() != 0)
            {
                if(approve_selected == FALSE)
                {
                    oledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_APPROVE, 0);
                }
                else
                {
                    oledBitmapDrawFlash(SSD1305_OLED_WIDTH-15, 0, BITMAP_DENY, 0);
                }
                approve_selected = !approve_selected;
                miniOledFlushEntireBufferToDisplay();
            }
        }   
    
        if ((input_answer == MINI_INPUT_RET_YES) && (approve_selected != FALSE))
        {
            return RETURN_OK;
        }
        else
        {
            return RETURN_NOK;
        }
    #endif
}
Пример #13
0
/*! \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
}
Пример #14
0
/*! \fn     getTouchedPositionAnswer(uint8_t led_mask)
*   \brief  Use the capacitive interface to get quarter position
*   \param  led_mask    Led mask for the touchdetection routine
*   \return Number between 0 and 5 for valid pos, -1 otherwise
*/
int8_t getTouchedPositionAnswer(uint8_t led_mask)
{
    #if defined(ALWAYS_ACCEPT_REQUESTS)
        // First quarter is discarded, it means we want yes or no!
        if (led_mask & LED_MASK_WHEEL_TLEFT)
        {
            return TOUCHPOS_RIGHT;
        }
        else
        {
            return TOUCHPOS_WHEEL_TLEFT;
        }
    #endif

    uint8_t incomingData[RAWHID_TX_SIZE];
    RET_TYPE touch_detect_result;
    
    // Switch on lights
    activityDetectedRoutine();
    
    // Clear possible remaining detection
    touchDetectionRoutine(led_mask);
    
    // Additional masking in case we only want left / right
    uint8_t additional_mask = 0xFF;
    if (led_mask == LED_MASK_WHEEL)
    {
        additional_mask = RETURN_LEFT_PRESSED | RETURN_RIGHT_PRESSED;
    }
    
    // Wait for a touch press
    do
    {
        // User interaction timeout or smartcard removed
        if ((hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED) || (isSmartCardAbsent() == RETURN_OK))
        {
            return -1;
        }
        // Read usb comms as the plugin could ask to cancel the request
        if ((getMooltipassParameterInEeprom(USER_REQ_CANCEL_PARAM) != FALSE) && (usbRawHidRecv(incomingData) == RETURN_COM_TRANSF_OK))
        {
            if (incomingData[HID_TYPE_FIELD] == CMD_CANCEL_REQUEST)
            {
                // Request cancelled
                return -1;
            }
            else
            {
                // Another packet (that shouldn't be sent!), ask to retry later...
                usbSendMessage(CMD_PLEASE_RETRY, 0, incomingData);
            }
        }
        touch_detect_result = touchDetectionRoutine(led_mask) & TOUCH_PRESS_MASK & additional_mask;
    }
    while (!touch_detect_result);
    
    // Prevent touches until the user lifts his finger
    touchInhibitUntilRelease();
    
    // Did the user press one of the two touch buttons?
    if (touch_detect_result & RETURN_LEFT_PRESSED)
    {
        return TOUCHPOS_LEFT;
    }
    else if (touch_detect_result & RETURN_RIGHT_PRESSED)
    {
        return TOUCHPOS_RIGHT;
    }
    else
    {
        return (int8_t)getWheelTouchDetectionQuarter();
    } 
}