diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index dcc8539ba..981aaa813 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -148,7 +148,6 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) { updateBatteryState(); if (switchTo(usbConnectedAppSnapshot())) { Ion::USB::DFU(true, GlobalPreferences::sharedGlobalPreferences()->dfuStatus(), GlobalPreferences::sharedGlobalPreferences()->getDfuLevel()); - GlobalPreferences::sharedGlobalPreferences()->dfuResetStep(); GlobalPreferences::sharedGlobalPreferences()->setDfuStatus(false); // Update LED when exiting DFU mode Ion::LED::updateColorWithPlugAndCharge(); diff --git a/apps/global_preferences.h b/apps/global_preferences.h index 5345bd21c..62a9dadd4 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -31,14 +31,9 @@ public: bool showPopUp() const { return m_showPopUp; } void setShowPopUp(bool showPopUp) { m_showPopUp = showPopUp; } bool dfuStatus() const { return m_dfuUnlocked; } - void setDfuStatus(bool status) { m_dfuUnlocked=status; } - int dfuCurrentStep() const { return m_dfuStep; } - void dfuIncreaseStep() { m_dfuStep++; } - void dfuResetStep() { m_dfuStep = 0; } + void setDfuStatus(bool status) { m_dfuUnlocked = status; } int getDfuLevel() const { return m_dfuProtectLevel; } void setDfuLevel(int level) { m_dfuProtectLevel = level; } - bool showDfuDeacAlert() const { return m_showDeacAlert; } - void setDfuDeacAlert(bool value) { m_showDeacAlert = value; } bool autocomplete() const { return m_autoComplete; } void setAutocomplete(bool autocomple) { m_autoComplete = autocomple; } int brightnessLevel() const { return m_brightnessLevel; } @@ -57,9 +52,7 @@ private: m_tempExamMode(ExamMode::Standard), m_showPopUp(true), m_dfuUnlocked(false), - m_dfuStep(0), m_dfuProtectLevel(0), - m_showDeacAlert(true), m_autoComplete(true), m_brightnessLevel(Ion::Backlight::MaxBrightness), m_font(KDFont::LargeFont) {} @@ -71,12 +64,8 @@ private: mutable ExamMode m_tempExamMode; bool m_showPopUp; bool m_dfuUnlocked; - int m_dfuStep; - int m_dfuProtectLevel; // 0: default; 1: OmegaMode; 2: Paranoid; 3: Paranoid++ - bool m_showDeacAlert; bool m_autoComplete; int m_brightnessLevel; - const KDFont * m_font; }; #endif diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 79ffa07e7..2174ddf9c 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -69,3 +69,11 @@ Date = "Datum" Time = "Uhrzeit" RTCWarning1 = "Das Aktivieren der Uhr verkürzt die" RTCWarning2 = "Akkulaufzeit im Bereitschaftsmodus." +USBExplanation1= "USB-Schutz schützt Ihren" +USBExplanation2= "Taschenrechner vor" +USBExplanation3= "unbeabsichtigter Verriegelung" +USBProtection= "USB-Schutz" +USBLevelProtect = "Akzeptierte Updates" +USBDefaultLevel = "Basierend auf Upsilon" +USBLowLevel = "Basierend auf Omega" +USBParanoidLevel = "Nichts" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index f86534a69..a0c5ce5f8 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -69,3 +69,11 @@ Date = "Date" Time = "Time" RTCWarning1 = "Enabling the clock drains the battery faster" RTCWarning2 = "when the calculator is powered off." +USBExplanation1= "The USB protection protects" +USBExplanation2= "the calculator from" +USBExplanation3= "unintentional locking" +USBProtection= "USB Protection" +USBLevelProtect = "Updates accepted" +USBDefaultLevel = "Based on Upsilon" +USBLowLevel = "Based on Omega" +USBParanoidLevel = "None" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 44c634316..adaf7704d 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -69,3 +69,11 @@ Date = "Fecha" Time = "Hora" RTCWarning1 = "Activar el reloj gasta la batería más rápido" RTCWarning2 = "cuando la calculadora está apagada." +USBExplanation1= "La protección USB protege" +USBExplanation2= "su calculadora del" +USBExplanation3= "bloqueo involuntario" +USBProtection= "Protección USB" +USBLevelProtect = "Actualizaciones aceptadas" +USBDefaultLevel = "Basado en Upsilon" +USBLowLevel = "Basado en Omega" +USBParanoidLevel = "Ninguno" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 0c00795ad..f2103455b 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -69,3 +69,11 @@ Date = "Date" Time = "Heure" RTCWarning1 = "Activer l'horloge décharge la batterie plus" RTCWarning2 = "vite quand la calculatrice est éteinte." +USBExplanation1= "La protection USB protège votre" +USBExplanation2= "calculatrice contre un verrouillage" +USBExplanation3= "non-intentionnel" +USBProtection= "Protection USB" +USBLevelProtect = "Mise à jour acceptées" +USBDefaultLevel = "Basées sur Upsilon" +USBLowLevel = "Basées sur Omega" +USBParanoidLevel = "Aucune" diff --git a/apps/settings/base.hu.i18n b/apps/settings/base.hu.i18n index e7c63d3a6..ae7e6cc7d 100644 --- a/apps/settings/base.hu.i18n +++ b/apps/settings/base.hu.i18n @@ -69,3 +69,12 @@ Date = "Datum" Time = "Óra" RTCWarning1 = "Amikor a számológép alvómódban van, az óra" RTCWarning2 = "használása az elemet gyorsabban meríti ki." +USBExplanation1= "Az USB-védelem megvédi" +USBExplanation2= "a számológépet a nem" +USBExplanation3= "szándékos reteszeléstől" +USBProtection= "USB védelem" +USBLevelProtect = "Elfogadott frissítések" +USBDefaultLevel = "Upsilon alapján" +USBLowLevel = "Omega alapján" +USBParanoidLevel = "Egyik sem" + diff --git a/apps/settings/base.it.i18n b/apps/settings/base.it.i18n index 831624d4d..5eb0d8930 100644 --- a/apps/settings/base.it.i18n +++ b/apps/settings/base.it.i18n @@ -69,3 +69,11 @@ Date = "Date" Time = "Time" RTCWarning1 = "Enabling the clock drains the battery faster" RTCWarning2 = "when the calculator is powered off." +USBExplanation1= "La protezione USB protegge" +USBExplanation2= "la calcolatrice dal" +USBExplanation3= "blocco involontario" +USBProtection= "Protezione USB" +USBLevelProtect = "Aggiornamenti accettati" +USBDefaultLevel = "Basato su Upsilon" +USBLowLevel = "A base di Omega" +USBParanoidLevel = "Nessuno" diff --git a/apps/settings/base.nl.i18n b/apps/settings/base.nl.i18n index 489415ca6..4423887fe 100644 --- a/apps/settings/base.nl.i18n +++ b/apps/settings/base.nl.i18n @@ -69,3 +69,11 @@ Date = "Date" Time = "Time" RTCWarning1 = "Enabling the clock drains the battery faster" RTCWarning2 = "when the calculator is powered off." +USBExplanation1= "USB-beveiliging beschermt uw" +USBExplanation2= "rekenmachine tegen" +USBExplanation3= "onbedoelde vergrendeling" +USBProtection= "USB-beveiliging" +USBLevelProtect = "Updates geaccepteerd" +USBDefaultLevel = "Gebaseerd op Upsilon" +USBLowLevel = "Op basis van Omega" +USBParanoidLevel = "Geen" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index c56c1d74f..927cac527 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -69,3 +69,11 @@ Date = "Date" Time = "Time" RTCWarning1 = "Enabling the clock drains the battery faster" RTCWarning2 = "when the calculator is powered off." +USBExplanation1= "A proteção USB protege" +USBExplanation2= "sua calculadora contra" +USBExplanation3= "bloqueios não intencionais" +USBProtection= "Proteção USB" +USBLevelProtect = "Atualizações aceitas" +USBDefaultLevel = "Baseado em Upsilon" +USBLowLevel = "Baseado em Ômega" +USBParanoidLevel = "Nenhum" diff --git a/apps/settings/base.universal.i18n b/apps/settings/base.universal.i18n new file mode 100644 index 000000000..124dc2112 --- /dev/null +++ b/apps/settings/base.universal.i18n @@ -0,0 +1,4 @@ +UsbSetting = "USB" +USBDefaultLevelDesc = "L0" +USBLowLevelDesc = "L1" +USBParanoidLevelDesc = "L2" diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index e28bab689..7277f85fc 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -15,7 +15,7 @@ constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMess constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; constexpr SettingsMessageTree s_modelDateTimeChildren[3] = {SettingsMessageTree(I18n::Message::ActivateClock), SettingsMessageTree(I18n::Message::Date), SettingsMessageTree(I18n::Message::Time)}; constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::Message::SymbolMultiplicationCross),SettingsMessageTree(I18n::Message::SymbolMultiplicationMiddleDot),SettingsMessageTree(I18n::Message::SymbolMultiplicationStar),SettingsMessageTree(I18n::Message::SymbolMultiplicationAutoSymbol)}; -constexpr SettingsMessageTree s_usbLevelSelector[3] = {SettingsMessageTree(I18n::Message::USBDefaultLevel), SettingsMessageTree(I18n::Message::USBLowLevel), SettingsMessageTree(I18n::Message::USBParanoidLevel)}; // , SettingsMessageTree(I18n::Message::USBMegaParanoidLevel) +constexpr SettingsMessageTree s_usbLevelSelector[3] = {SettingsMessageTree(I18n::Message::USBDefaultLevel), SettingsMessageTree(I18n::Message::USBLowLevel), SettingsMessageTree(I18n::Message::USBParanoidLevel)}; constexpr SettingsMessageTree s_usbSteps[2] = {SettingsMessageTree(I18n::Message::USBProtection), SettingsMessageTree(I18n::Message::USBLevelProtect, s_usbLevelSelector)}; constexpr SettingsMessageTree s_symbolFunctionChildren[3] = {SettingsMessageTree(I18n::Message::SymbolDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgFunction)}; constexpr SettingsMessageTree s_modelMathOptionsChildren[6] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren), SettingsMessageTree(I18n::Message::SymbolFunction, s_symbolFunctionChildren), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren)}; diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index 95c0b571e..cb25548a3 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -8,14 +8,14 @@ using namespace Shared; namespace Settings { constexpr SettingsMessageTree s_modelMenu[] = - {SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren), + {SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren), SettingsMessageTree(I18n::Message::Language), SettingsMessageTree(I18n::Message::Country), SettingsMessageTree(I18n::Message::ExamMode, ExamModeConfiguration::s_modelExamChildren), #ifdef HAS_CODE - SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren), + SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren), #endif SettingsMessageTree(I18n::Message::UsbSetting, s_usbSteps), SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren), diff --git a/apps/settings/sub_menu/usb_info_controller.cpp b/apps/settings/sub_menu/usb_info_controller.cpp index f31bd3f82..3b518b042 100644 --- a/apps/settings/sub_menu/usb_info_controller.cpp +++ b/apps/settings/sub_menu/usb_info_controller.cpp @@ -16,119 +16,86 @@ using namespace Shared; namespace Settings { -UsbInfoController::UsbInfoController(Responder *parentResponder) : GenericSubController(parentResponder), - m_usbprotectlevel(this), - m_dfuLevel(KDFont::LargeFont, KDFont::SmallFont), - m_contentView(&m_selectableTableView) { - for (int i = 0; i < k_maxSwitchCells; i++) { - m_switchCells[i].setMessageFont(KDFont::LargeFont); - //Ancien code au cas ou on souhaite ajouter d'autres éléments dans le menu - // m_cell[i].setMessageFont(KDFont::LargeFont); - // m_cell[i].setAccessoryFont(KDFont::SmallFont); - // m_cell[i].setAccessoryTextColor(Palette::SecondaryText); - } +UsbInfoController::UsbInfoController(Responder *parentResponder): + GenericSubController(parentResponder), + m_usbProtectionLevelController(this), + m_dfuLevel(KDFont::LargeFont, KDFont::SmallFont) +{ + for (int i = 0; i < k_maxSwitchCells; i++) { + m_switchCells[i].setMessageFont(KDFont::LargeFont); + } } bool UsbInfoController::handleEvent(Ion::Events::Event event) { - if ((Ion::Events::OK == event || Ion::Events::EXE == event) && selectedRow() == 0) { - if(GlobalPreferences::sharedGlobalPreferences()->showDfuDeacAlert()){ - GlobalPreferences::sharedGlobalPreferences()->setDfuDeacAlert(false); - Container::activeApp()->displayWarning(I18n::Message::USBDeacAlert1, I18n::Message::USBDeacAlert2); - return true; - } - if (!GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) { - if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { - Ion::LED::setColor(KDColorPurple); - Ion::LED::setBlinking(500, 0.5f); - } - GlobalPreferences::sharedGlobalPreferences()->setDfuStatus(true); - Container::activeApp()->displayWarning(I18n::Message::DfuWarning1, I18n::Message::DfuWarning2); - } else { - if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { - Ion::LED::setColor(KDColorBlack); - } - GlobalPreferences::sharedGlobalPreferences()->setDfuStatus(false); - } - m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); - AppsContainer::sharedAppsContainer()->redrawWindow(true); - return true; + if ((Ion::Events::OK == event || Ion::Events::EXE == event) && selectedRow() == 0) { + if (!GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) { + if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { + Ion::LED::setColor(KDColorPurple); + Ion::LED::setBlinking(500, 0.5f); + } + GlobalPreferences::sharedGlobalPreferences()->setDfuStatus(true); + Container::activeApp()->displayWarning(I18n::Message::DfuWarning1, I18n::Message::DfuWarning2); + } else { + if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { + Ion::LED::setColor(KDColorBlack); + } + GlobalPreferences::sharedGlobalPreferences()->setDfuStatus(false); } - - if (GlobalPreferences::sharedGlobalPreferences()->dfuStatus() && event != Ion::Events::USBPlug && event != Ion::Events::USBEnumeration) { - Container::activeApp()->displayWarning(I18n::Message::UsbSetting, I18n::Message::USBSettingDeact); - return true; - } - - if ((Ion::Events::OK == event || Ion::Events::EXE == event) && selectedRow() == 1) { - GenericSubController *subController = &m_usbprotectlevel; - subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(1)); - StackViewController *stack = stackController(); - m_lastSelect = selectedRow(); - stack->push(subController); - return true; - } - GlobalPreferences::sharedGlobalPreferences()->setDfuDeacAlert(true); - return GenericSubController::handleEvent(event); + m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); + AppsContainer::sharedAppsContainer()->redrawWindow(true); + return true; + } + // We cannot use things like willExitResponderChain because this view can disappear due to an USB connection, + // and in this case we must keep the DFU status. + if ((Ion::Events::Left == event || Ion::Events::Home == event) && GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) { + Container::activeApp()->displayWarning(I18n::Message::USBProtectionReanabled); + GlobalPreferences::sharedGlobalPreferences()->setDfuStatus(false); + } + if ((Ion::Events::OK == event || Ion::Events::EXE == event) && selectedRow() == 1) { + GenericSubController *subController = &m_usbProtectionLevelController; + subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(1)); + StackViewController *stack = stackController(); + m_lastSelect = selectedRow(); + stack->push(subController); + return true; + } + return GenericSubController::handleEvent(event); } HighlightCell *UsbInfoController::reusableCell(int index, int type) { - assert(type == 2 || type == 1); - if (type == 2) { - assert(index >= 0 && index < k_maxSwitchCells); - return &m_switchCells[index]; - } - return &m_dfuLevel; + assert(index == 0 || index == 1); + return index == 0 ? &m_switchCell : &m_dfuLevelCell; } int UsbInfoController::reusableCellCount(int type) { - assert(type == 2 || type == 1); - if (type == 2) { - return k_maxSwitchCells; - } - return 1; + assert(type == 0); + return 1; } void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) { - GenericSubController::willDisplayCellForIndex(cell, index); + GenericSubController::willDisplayCellForIndex(cell, index); - if (index == 0) { - MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *)cell; - SwitchView *mySwitch = (SwitchView *)myCell->accessoryView(); - mySwitch->setState(!GlobalPreferences::sharedGlobalPreferences()->dfuStatus()); - } else if (index == 1) { - MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *)cell; - int currentLevel = GlobalPreferences::sharedGlobalPreferences()->getDfuLevel(); - if (currentLevel == 0) { - // mcell->setSubtitle(I18n::Message::USBDefaultLevel); - mcell->setSubtitle(I18n::Message::USBDefaultLevelDesc); - } else if (currentLevel == 1) { - // mcell->setSubtitle(I18n::Message::USBLowLevel); - mcell->setSubtitle(I18n::Message::USBLowLevelDesc); - } else if (currentLevel == 2) { - // mcell->setSubtitle(I18n::Message::USBParanoidLevel); - mcell->setSubtitle(I18n::Message::USBParanoidLevelDesc); - } else { - // mcell->setSubtitle(I18n::Message::USBMegaParanoidLevel); - mcell->setSubtitle(I18n::Message::USBMegaParanoidLevelDesc); - } - } -} - -int UsbInfoController::typeAtLocation(int i, int j) { - switch (j) { - case 0: - return 2; - default: - return 1; + if (index == 0) { + MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *)cell; + SwitchView *mySwitch = (SwitchView *)myCell->accessoryView(); + mySwitch->setState(!GlobalPreferences::sharedGlobalPreferences()->dfuStatus()); + } else if (index == 1) { + MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *)cell; + int currentLevel = GlobalPreferences::sharedGlobalPreferences()->getDfuLevel(); + if (currentLevel == 0) { + mcell->setSubtitle(I18n::Message::USBDefaultLevelDesc); + } else if (currentLevel == 1) {; + mcell->setSubtitle(I18n::Message::USBLowLevelDesc); + } else { + assert(currentLevel == 2); + mcell->setSubtitle(I18n::Message::USBParanoidLevelDesc); } + } } void UsbInfoController::didEnterResponderChain(Responder *previousFirstResponder) { - m_contentView.reload(); - - if (numberOfInfoLines() > 0) { - I18n::Message infoMessages[] = {I18n::Message::USBE16_expl1, I18n::Message::USBE16_expl2, I18n::Message::USBE16_expl3}; - m_contentView.setMessages(infoMessages, numberOfInfoLines()); - } + m_selectableTableView.reload(); + I18n::Message infoMessages[] = {I18n::Message::USBExplanation1, I18n::Message::USBExplanation2, I18n::Message::USBExplanation3}; + m_selectableTableView.setMessages(infoMessages, k_numberOfExplanationMessages); } } diff --git a/apps/settings/sub_menu/usb_info_controller.h b/apps/settings/sub_menu/usb_info_controller.h index 1bd602883..d80356985 100644 --- a/apps/settings/sub_menu/usb_info_controller.h +++ b/apps/settings/sub_menu/usb_info_controller.h @@ -19,16 +19,12 @@ class UsbInfoController : public GenericSubController { HighlightCell* reusableCell(int index, int type) override; int reusableCellCount(int type) override; void willDisplayCellForIndex(HighlightCell* cell, int index) override; - int typeAtLocation(int i, int j) override; private: - static constexpr int k_numberOfInfoE16MessageLines = 3; - int numberOfInfoLines() const { return k_numberOfInfoE16MessageLines; }; - static constexpr int k_maxSwitchCells = 1; - MessageTableCellWithSwitch m_switchCells[k_maxSwitchCells]; - UsbProtectionLevelController m_usbprotectlevel; - MessageTableCellWithChevronAndMessage m_dfuLevel; - SelectableViewWithMessages m_contentView; + static constexpr int k_numberOfExplanationMessages = 3; + MessageTableCellWithSwitch m_switchCell; + UsbProtectionLevelController m_usbProtectionLevelController; + MessageTableCellWithChevronAndMessage m_dfuLevelCell; }; } diff --git a/apps/usb/base.de.i18n b/apps/usb/base.de.i18n index 0cf269f75..a79b6c49a 100644 --- a/apps/usb/base.de.i18n +++ b/apps/usb/base.de.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "getomega.dev/ide." ConnectedMessage4 = "Drücken Sie die Zurück-Taste am" ConnectedMessage5 = "Taschenrechner oder Kabel abziehen," ConnectedMessage6 = "um die Verbindung zu trennen." -DfuStatus1 = "Status des Rechners:" +DfuStatus = "Status des Rechners:" DfuStatusProtected = "GESCHÜTZT" -DfuStatusUnProtected = "UNGESCHÜTZT" +DfuStatusUnprotected = "UNGESCHÜTZT" USBProtectionLevel0 = "Standardschutz" USBProtectionLevel1 = "Omega Schutz" USBProtectionLevel2 = "Systemschutz" diff --git a/apps/usb/base.en.i18n b/apps/usb/base.en.i18n index b7411ff54..b660f9da4 100644 --- a/apps/usb/base.en.i18n +++ b/apps/usb/base.en.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "getomega.dev/ide" ConnectedMessage4 = "Press the BACK key of your" ConnectedMessage5 = "calculator or unplug it to" ConnectedMessage6 = "disconnect it." -DfuStatus1 = "Calculator status:" +DfuStatus = "Calculator status:" DfuStatusProtected = "PROTECTED" -DfuStatusUnProtected = "UNPROTECTED" +DfuStatusUnprotected = "UNPROTECTED" USBProtectionLevel0 = "Default Protection" USBProtectionLevel1 = "Omega Protection" USBProtectionLevel2 = "System Protection" diff --git a/apps/usb/base.es.i18n b/apps/usb/base.es.i18n index 0ccebf53d..e6e396e94 100644 --- a/apps/usb/base.es.i18n +++ b/apps/usb/base.es.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "getomega.dev/ide" ConnectedMessage4 = "Pulse el botón RETURN de la" ConnectedMessage5 = "calculadora o desenchúfela para" ConnectedMessage6 = "desconectarla." -DfuStatus1 = "Estado de la calculadora:" +DfuStatus = "Estado de la calculadora:" DfuStatusProtected = "PROTEGIDO" -DfuStatusUnProtected = "DESABRIGADO" +DfuStatusUnprotected = "DESABRIGADO" USBProtectionLevel0 = "Protección predeterminada" USBProtectionLevel1 = "Protección Omega" USBProtectionLevel2 = "Protección del sistema" diff --git a/apps/usb/base.fr.i18n b/apps/usb/base.fr.i18n index d1a4e9448..f81365671 100644 --- a/apps/usb/base.fr.i18n +++ b/apps/usb/base.fr.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "getomega.dev/ide" ConnectedMessage4 = "Appuyez sur la touche RETOUR" ConnectedMessage5 = "de la calculatrice ou débranchez-la" ConnectedMessage6 = "pour la déconnecter." -DfuStatus1 = "Etat de la calculatrice:" +DfuStatus = "Etat de la calculatrice:" DfuStatusProtected = "PROTÉGÉE" -DfuStatusUnProtected = "NON PROTÉGÉE" +DfuStatusUnprotected = "NON PROTÉGÉE" USBProtectionLevel0 = "Default Protection" USBProtectionLevel1 = "Omega Protection" USBProtectionLevel2 = "System Protection" diff --git a/apps/usb/base.hu.i18n b/apps/usb/base.hu.i18n index d432c76d3..141101767 100644 --- a/apps/usb/base.hu.i18n +++ b/apps/usb/base.hu.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "fel getomega.dev/ide ra." ConnectedMessage4 = "Nyomjon majd a VISSZA gombra" ConnectedMessage5 = "vagy huzza ki a kábelt azért" ConnectedMessage6 = "hogy a másolás véget érjen." -DfuStatus1 = "Számológép állapota:" +DfuStatus = "Számológép állapota:" DfuStatusProtected = "VÉDETT" -DfuStatusUnProtected = "VÉDTELEN" +DfuStatusUnprotected = "VÉDTELEN" USBProtectionLevel0 = "Alapértelmezett védelem" USBProtectionLevel1 = "Omega védelem" USBProtectionLevel2 = "Rendszervédelem" diff --git a/apps/usb/base.it.i18n b/apps/usb/base.it.i18n index 2fbed5da8..54b29beae 100644 --- a/apps/usb/base.it.i18n +++ b/apps/usb/base.it.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "getomega.dev/ide" ConnectedMessage4 = "Premere sul tasto INDIETRO della" ConnectedMessage5 = "calcolatrice o scollegatela per" ConnectedMessage6 = "disconnetterla." -DfuStatus1 = "Stato della calcolatrice:" +DfuStatus = "Stato della calcolatrice:" DfuStatusProtected = "PROTETTO" -DfuStatusUnProtected = "INDIFESO" +DfuStatusUnprotected = "INDIFESO" USBProtectionLevel0 = "Protezione predefinita" USBProtectionLevel1 = "Protezione Omega" USBProtectionLevel2 = "Protezione del sistema" diff --git a/apps/usb/base.nl.i18n b/apps/usb/base.nl.i18n index e05db7f3f..2f5684169 100644 --- a/apps/usb/base.nl.i18n +++ b/apps/usb/base.nl.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "getomega.dev/ide" ConnectedMessage4 = "Druk op de TERUG toets van je" ConnectedMessage5 = "rekenmachine of verwijder de" ConnectedMessage6 = " kabel om hem los te koppelen." -DfuStatus1 = "Rekenmachine status:" +DfuStatus = "Rekenmachine status:" DfuStatusProtected = "BESCHERMD" -DfuStatusUnProtected = "NIET BESCHERMD" +DfuStatusUnprotected = "NIET BESCHERMD" USBProtectionLevel0 = "Standaardbeveiliging" USBProtectionLevel1 = "Omega Bescherming" USBProtectionLevel2 = "Systeembeveiliging" diff --git a/apps/usb/base.pt.i18n b/apps/usb/base.pt.i18n index 91dd85e3c..a87f034ea 100644 --- a/apps/usb/base.pt.i18n +++ b/apps/usb/base.pt.i18n @@ -5,9 +5,9 @@ ConnectedMessage3 = "getomega.dev/ide" ConnectedMessage4 = "Pressione o botão RETURN na" ConnectedMessage5 = "calculadora ou desligue-a para a" ConnectedMessage6 = "desconectar." -DfuStatus1 = "Status da calculadora:" +DfuStatus = "Status da calculadora:" DfuStatusProtected = "PROTEGIDO" -DfuStatusUnProtected = "DESPROTEGIDO" +DfuStatusUnprotected = "DESPROTEGIDO" USBProtectionLevel0 = "Proteção padrão" USBProtectionLevel1 = "Proteção Ômega" USBProtectionLevel2 = "Proteção do sistema" diff --git a/apps/usb/usb_connected_controller.cpp b/apps/usb/usb_connected_controller.cpp index deb3abff0..e63cf699b 100644 --- a/apps/usb/usb_connected_controller.cpp +++ b/apps/usb/usb_connected_controller.cpp @@ -4,137 +4,86 @@ namespace USB { +static constexpr I18n::Message sUSBConnectedMessages[k_numberOfUSBMessages] = { + I18n::Message::USBConnected, + I18n::Message::ConnectedMessage1, + I18n::Message::ConnectedMessage2, + I18n::Message::ConnectedMessage3, + I18n::Message::BlankMessage, + I18n::Message::ConnectedMessage4, + I18n::Message::ConnectedMessage5, + I18n::Message::ConnectedMessage6, + I18n::Message::DfuStatus}; - static I18n::Message sUSBConnectedMessagesProtection0[10] = { - I18n::Message::USBConnected, - I18n::Message::ConnectedMessage1, - I18n::Message::ConnectedMessage2, - I18n::Message::ConnectedMessage3, - I18n::Message::BlankMessage, - I18n::Message::ConnectedMessage4, - I18n::Message::ConnectedMessage5, - I18n::Message::ConnectedMessage6, - I18n::Message::DfuStatus1, - I18n::Message::USBProtectionLevel0}; - - static I18n::Message sUSBConnectedMessagesProtection1[10] = { - I18n::Message::USBConnected, - I18n::Message::ConnectedMessage1, - I18n::Message::ConnectedMessage2, - I18n::Message::ConnectedMessage3, - I18n::Message::BlankMessage, - I18n::Message::ConnectedMessage4, - I18n::Message::ConnectedMessage5, - I18n::Message::ConnectedMessage6, - I18n::Message::DfuStatus1, - I18n::Message::USBProtectionLevel1}; - - static I18n::Message sUSBConnectedMessagesProtection2[10] = { - I18n::Message::USBConnected, - I18n::Message::ConnectedMessage1, - I18n::Message::ConnectedMessage2, - I18n::Message::ConnectedMessage3, - I18n::Message::BlankMessage, - I18n::Message::ConnectedMessage4, - I18n::Message::ConnectedMessage5, - I18n::Message::ConnectedMessage6, - I18n::Message::DfuStatus1, - I18n::Message::USBProtectionLevel2}; +static constexpr KDColor sUSBConnectedFGColors[] = { + Palette::PrimaryText, + Palette::PrimaryText, + Palette::PrimaryText, + Palette::AccentText, + KDColorWhite, + Palette::PrimaryText, + Palette::PrimaryText, + Palette::PrimaryText, + Palette::PrimaryText, + Palette::AccentText}; - static I18n::Message sUSBConnectedMessagesUnProtected[10] = { - I18n::Message::USBConnected, - I18n::Message::ConnectedMessage1, - I18n::Message::ConnectedMessage2, - I18n::Message::ConnectedMessage3, - I18n::Message::BlankMessage, - I18n::Message::ConnectedMessage4, - I18n::Message::ConnectedMessage5, - I18n::Message::ConnectedMessage6, - I18n::Message::DfuStatus1, - I18n::Message::DfuStatusUnProtected}; - - static KDColor sUSBConnectedFGColors[] = { - Palette::PrimaryText, - Palette::PrimaryText, - Palette::PrimaryText, - Palette::AccentText, - KDColorWhite, - Palette::PrimaryText, - Palette::PrimaryText, - Palette::PrimaryText, - Palette::PrimaryText, - Palette::AccentText}; - - static KDColor sUSBConnectedBGColors[] = { - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard, - Palette::BackgroundHard}; - - USBConnectedController::USBConnectedController() : ViewController(nullptr), step(0), already_init(false), m_messageView(sUSBConnectedMessagesProtection0, sUSBConnectedFGColors, sUSBConnectedBGColors, 10) - { - if(already_init){ - return; - } - if (step == 0 && GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) - { - getMessageView()->update(sUSBConnectedMessagesUnProtected, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - }else if(step == 0){ - if(GlobalPreferences::sharedGlobalPreferences()->getDfuLevel() == 1){ - getMessageView()->update(sUSBConnectedMessagesProtection1, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - }else if(GlobalPreferences::sharedGlobalPreferences()->getDfuLevel() == 2){ - getMessageView()->update(sUSBConnectedMessagesProtection2, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - } - } - // else if (step == 1 && GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) - // { - // getMessageView()->update(sUSBConnectedMessages2UnProtected, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - // } - // else if (step == 1 && !GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) - // { - // getMessageView()->update(sUSBConnectedMessages2Protected, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - // } - already_init = true; - } - - // bool USBConnectedController::handleEvent(Ion::Events::Event event) - // { - // if (event.isKeyboardEvent()) - // { - // // Ne fonctionne pas pour l'instant fait bugger les events - // // if (step == 0) - // // { - // // if (GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) - // // { - // // getMessageView()->update(sUSBConnectedMessagesUnProtected, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - // // } - // // else - // // { - // // getMessageView()->update(sUSBConnectedMessagesProtected, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - // // } - // // step = 1; - // // } - // // else - // // { - // // if (GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) - // // { - // // getMessageView()->update(sUSBConnectedMessages2UnProtected, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - // // } - // // else - // // { - // // getMessageView()->update(sUSBConnectedMessages2Protected, sUSBConnectedFGColors, sUSBConnectedBGColors, 10); - // // } - // // step = 0; - // // } - // return false; - // } - // return false; - // } +USBConnectedController::USBConnectedController() : + ViewController(nullptr) +{ + +} + +USBConnectedController::ContentView::ContentView(KDColor * fgcolors, KDColor * bgcolors, uint8_t numberOfMessages) { + // We set the styles of the messages + for (uint8_t i = 0; i < k_numberOfMessages; i++) { + m_messageTextViews[i].setFont(i == 0 ? KDFont::LargeFont : KDFont::SmallFont); + m_messageTextViews[i].setAlignment(0.5f, 0.5f); + m_messageTextViews[i].setTextColor(fgcolors[i]); + m_messageTextViews[i].setBackgroundColor(Palette::BackgroundHard); + } + + // We set the texts of the firsts defaults messages + for (uint8_t i = 0; i < k_numberOfUSBMessages; i++) { + m_messageTextViews[i].setText(sUSBConnectedMessages[i]); + } + + // Last message, depending of the USB protection level + if (GlobalPreferences::sharedGlobalPreferences()->dfuStatus()) { + m_messageTextViews[i].setText(DfuStatusUnprotected); + } else { + int protectionLevel = GlobalPreferences::sharedGlobalPreferences()->getDfuLevel(); + switch (protectionLevel) { + case 0: + m_messageTextViews[9].setText(USBProtectionLevel0); + break; + case 1: + m_messageTextViews[9].setText(USBProtectionLevel1); + break; + default: + assert(protectionLevel == 2); + m_messageTextViews[9].setText(USBProtectionLevel2); + break; + } + } +} + +void USBConnectedController::ContentView::drawRect(KDContext *ctx, KDRect rect) const { + ctx->fillRect(bounds(), Palette::BackgroundHard); +} + +View *USBConnectedController::ContentView::subviewAtIndex(int index) { + assert(index < k_numberOfMessages); + return &(m_messageTextViews[index]); +} + +void USBConnectedController::ContentView::layoutSubviews(bool force) { + KDCoordinate width = bounds().width(); + KDCoordinate titleHeight = m_messageTextViews[0].minimalSizeForOptimalDisplay().height(); + KDCoordinate textHeight = KDFont::SmallFont->glyphSize().height(); + m_messageTextViews[0].setFrame(KDRect(0, k_titleMargin, width, titleHeight), force); + for (uint8_t i = 1; i < k_numberOfMessages; i++) { + m_messageTextViews[i].setFrame(KDRect(0, k_paragraphHeight + (i - 1) * textHeight, width, textHeight), force); + } +} } diff --git a/apps/usb/usb_connected_controller.h b/apps/usb/usb_connected_controller.h index b2f5a269f..5fd0675fd 100644 --- a/apps/usb/usb_connected_controller.h +++ b/apps/usb/usb_connected_controller.h @@ -2,7 +2,6 @@ #define USB_USB_CONNECTED_CONTROLLER_H #include -#include "usb_view.h" namespace USB { @@ -12,13 +11,23 @@ public: View * view() override { return &m_messageView; } USBView * getMessageView() {return &m_messageView; } bool handleEvent(Ion::Events::Event event) override { return false; }; -private: - int step; - bool already_init; - USBView m_messageView; + public: + ContentView(KDColor * fgcolors, KDColor * bgcolors); + void drawRect(KDContext * ctx, KDRect rect) const override; + protected: + int numberOfSubviews() const override { return k_numberOfMessages; } + View * subviewAtIndex(int index) override; + void layoutSubviews(bool force = false) override; + private: + constexpr static KDCoordinate k_titleMargin = 30; + constexpr static KDCoordinate k_paragraphHeight = 80; + constexpr static uint8_t k_numberOfUSBMessages = 9; + constexpr static uint8_t k_numberOfMessages = k_numberOfUSBMessages + 1; + MessageTextView m_messageTextViews[k_numberOfMessages]; + }; + ContentView m_contentView; }; } - #endif diff --git a/build/targets.device.mak b/build/targets.device.mak index 850cbf076..27b8d1a97 100644 --- a/build/targets.device.mak +++ b/build/targets.device.mak @@ -72,4 +72,4 @@ binpack: $(BUILD_DIR)/flasher.light.bin $(BUILD_DIR)/epsilon.onboarding.two_bina cp $(BUILD_DIR)/epsilon.onboarding.internal.bin $(BUILD_DIR)/epsilon.onboarding.external.bin $(BUILD_DIR)/binpack cd $(BUILD_DIR) && for binary in flasher.light.bin epsilon.onboarding.internal.bin epsilon.onboarding.external.bin; do shasum -a 256 -b binpack/$${binary} > binpack/$${binary}.sha256;done cd $(BUILD_DIR) && tar cvfz binpack-$(MODEL)-`git rev-parse HEAD | head -c 7`.tgz binpack/* - $(PYTHON) build/device/secure_ext.py $(BUILD_DIR)/epsilon.onboarding.external.bin \ No newline at end of file + $(PYTHON) build/device/secure_ext.py $(BUILD_DIR)/epsilon.onboarding.external.bin diff --git a/ion/src/device/n0110/drivers/board.cpp b/ion/src/device/n0110/drivers/board.cpp index 228fbe6fc..caca26ea3 100644 --- a/ion/src/device/n0110/drivers/board.cpp +++ b/ion/src/device/n0110/drivers/board.cpp @@ -29,7 +29,7 @@ void initMPU() { // 1.1 Memory barrier Cache::dmb(); - // 1.2 Disable fault exceptions + // 1.2 Enable fault exceptions CORTEX.SHCRS()->setMEMFAULTENA(true); CORTEX.SHCRS()->setBUSFAULTENA(true); CORTEX.SHCRS()->setUSGFAULTENA(true); diff --git a/ion/src/device/shared/boot/isr.h b/ion/src/device/shared/boot/isr.h index be46adee9..e0f8da160 100644 --- a/ion/src/device/shared/boot/isr.h +++ b/ion/src/device/shared/boot/isr.h @@ -8,11 +8,12 @@ extern "C" { void bf_abort(); void uf_abort(); void nmi_abort(); +// Here and below, we mean init the abort handler, not the opposite void abort_init(); void abort_core(const char *); +void abort_screen(const char *); void abort_sleeping(); void abort_economy(); -void abort_screen(const char *); void start(); void abort(); void isr_systick(); diff --git a/ion/src/device/shared/boot/rt0.cpp b/ion/src/device/shared/boot/rt0.cpp index 6444117f0..24b9cb807 100644 --- a/ion/src/device/shared/boot/rt0.cpp +++ b/ion/src/device/shared/boot/rt0.cpp @@ -1,3 +1,4 @@ +#include "isr.h" #include #include #include @@ -27,13 +28,13 @@ typedef void (*cxx_constructor)(); extern "C" { -extern char _data_section_start_flash; -extern char _data_section_start_ram; -extern char _data_section_end_ram; -extern char _bss_section_start_ram; -extern char _bss_section_end_ram; -extern cxx_constructor _init_array_start; -extern cxx_constructor _init_array_end; + extern char _data_section_start_flash; + extern char _data_section_start_ram; + extern char _data_section_end_ram; + extern char _bss_section_start_ram; + extern char _bss_section_end_ram; + extern cxx_constructor _init_array_start; + extern cxx_constructor _init_array_end; } /* In order to ensure that this method is execute from the external flash, we @@ -45,8 +46,8 @@ static void __attribute__((noinline)) external_flash_start() { * happening during the on boarding app. The backlight will be initialized * after the Power-On Self-Test if there is one or before switching to the * home app otherwise. */ - Ion::Device::Board::initPeripherals(false); - return ion_main(0, nullptr); + Ion::Device::Board::initPeripherals(false); + return ion_main(0, nullptr); } /* This additional function call 'jump_to_external_flash' serves two purposes: @@ -219,6 +220,154 @@ void __attribute__((noinline)) uf_abort() { abort_core("USAGEFAULT"); } +void __attribute__((noinline)) abort_init() { + Ion::Device::Board::shutdownPeripherals(true); + Ion::Device::Board::initPeripherals(false); + Ion::Timing::msleep(100); + Ion::Backlight::init(); + Ion::LED::setColor(KDColorRed); + Ion::Backlight::setBrightness(180); +} + +void __attribute__((noinline)) abort_economy() { + int brightness = Ion::Backlight::brightness(); + bool plugged = Ion::USB::isPlugged(); + while (brightness > 0) { + brightness--; + Ion::Backlight::setBrightness(brightness); + Ion::Timing::msleep(50); + if(plugged || (!plugged && Ion::USB::isPlugged())){ + Ion::Backlight::setBrightness(180); + return; + } + } + Ion::Backlight::shutdown(); + while (1) { + Ion::Device::Power::sleepConfiguration(); + Ion::Device::WakeUp::onUSBPlugging(); + Ion::Device::WakeUp::onChargingEvent(); + Ion::Device::Power::internalFlashSuspend(true); + if (!plugged && Ion::USB::isPlugged()) { + break; + } + plugged = Ion::USB::isPlugged(); + }; + Ion::Device::Board::setStandardFrequency(Ion::Device::Board::Frequency::High); + Ion::Backlight::init(); + Ion::Backlight::setBrightness(180); +} + +void __attribute__((noinline)) abort_sleeping() { + if (Ion::Battery::level() != Ion::Battery::Charge::EMPTY) { + return; + } + // We don't use Ion::Power::suspend because we don't want to move the exam buffer into the internal + Ion::Device::Board::shutdownPeripherals(true); + bool plugged = Ion::USB::isPlugged(); + while (true) { + Ion::Device::Battery::initGPIO(); + Ion::Device::USB::initGPIO(); + Ion::Device::LED::init(); + Ion::Device::Power::sleepConfiguration(); + Ion::Device::Board::shutdownPeripherals(true); + Ion::Device::WakeUp::onUSBPlugging(); + Ion::Device::WakeUp::onChargingEvent(); + Ion::Device::Power::internalFlashSuspend(true); + Ion::Device::USB::initGPIO(); + if (!plugged && Ion::USB::isPlugged()) { + break; + } + plugged = Ion::USB::isPlugged(); + } + Ion::Device::Board::setStandardFrequency(Ion::Device::Board::Frequency::High); + abort_init(); +} + +void __attribute__((noinline)) abort_core(const char * text) { + Ion::Timing::msleep(100); + int counting; + while (true) { + counting = 0; + if (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) { + abort_sleeping(); + abort_screen(text); + } + + Ion::USB::enable(); + Ion::Battery::Charge previous_state = Ion::Battery::level(); + while (!Ion::USB::isEnumerated()) { + if (Ion::Battery::level() == Ion::Battery::Charge::LOW) { + if (previous_state != Ion::Battery::Charge::LOW) { + previous_state = Ion::Battery::Charge::LOW; + counting = 0; + } + Ion::Timing::msleep(500); + if (counting >= 20) { + abort_sleeping(); + abort_screen(text); + counting = -1; + } + counting++; + + } else { + if (previous_state == Ion::Battery::Charge::LOW) { + previous_state = Ion::Battery::level(); + counting = 0; + } + Ion::Timing::msleep(100); + if (counting >= 300) { + abort_economy(); + counting = -1; + } + counting++; + } + } + Ion::USB::DFU(false, false, 0); + } +} + +void __attribute__((noinline)) abort_screen(const char * text){ + KDRect screen = KDRect(0, 0, Ion::Display::Width, Ion::Display::Height); + Ion::Display::pushRectUniform(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), KDColor::RGB24(0xffffff)); + KDContext* ctx = KDIonContext::sharedContext(); + ctx->setOrigin(KDPointZero); + ctx->setClippingRect(screen); + ctx->drawString("UPSILON CRASH", KDPoint(90, 10), KDFont::LargeFont, KDColorRed, KDColor::RGB24(0xffffff)); + ctx->drawString("An error occurred", KDPoint(10, 30), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("If you have some important data, please", KDPoint(10, 45), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("use bit.ly/upsiBackup to backup them.", KDPoint(10, 60), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("YOU WILL LOSE ALL YOUR DATA", KDPoint(10, 85), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("→ You can try to reboot by presssing the", KDPoint(10, 110), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("reset button at the back of the calculator", KDPoint(10, 125), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("→ If Upsilon keeps crashing, you can connect", KDPoint(10, 140), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("the calculator to a computer or a phone", KDPoint(10, 160), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString("and try to reinstall Upsilon", KDPoint(10, 175), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff)); + ctx->drawString(text, KDPoint(220, 200), KDFont::SmallFont, KDColorRed, KDColor::RGB24(0xffffff)); +} + +void __attribute__((noinline)) abort() { + abort_init(); + abort_screen("HARDFAULT"); + abort_core("HARDFAULT"); +} + +void __attribute__((noinline)) nmi_abort() { + abort_init(); + abort_screen("NMIFAULT"); + abort_core("NMIFAULT"); +} + +void __attribute__((noinline)) bf_abort() { + abort_init(); + abort_screen("BUSFAULT"); + abort_core("BUSFAULT"); +} +void __attribute__((noinline)) uf_abort() { + abort_init(); + abort_screen("USAGEFAULT"); + abort_core("USAGEFAULT"); +} + /* When 'start' is executed, the external flash is supposed to be shutdown. We * thus forbid inlining to prevent executing this code from external flash * (just in case 'start' was to be called from the external flash). */ @@ -252,9 +401,9 @@ void __attribute__((noinline)) start() { * call the pointed function. */ #define SUPPORT_CPP_GLOBAL_CONSTRUCTORS 0 #if SUPPORT_CPP_GLOBAL_CONSTRUCTORS - for (cxx_constructor* c = &_init_array_start; c < &_init_array_end; c++) { - (*c)(); - } + for (cxx_constructor* c = &_init_array_start; c < &_init_array_end; c++) { + (*c)(); + } #else /* In practice, static initialized objects are a terrible idea. Since the init * order is not specified, most often than not this yields the dreaded static diff --git a/ion/src/device/shared/usb/calculator.cpp b/ion/src/device/shared/usb/calculator.cpp index 4d3818601..6d0174390 100644 --- a/ion/src/device/shared/usb/calculator.cpp +++ b/ion/src/device/shared/usb/calculator.cpp @@ -12,7 +12,6 @@ void Calculator::PollAndReset(bool exitWithKeyboard, bool unlock, int level) { Ion::Device::SerialNumber::copy(serialNumber); Calculator c(serialNumber); - /* Leave DFU mode if the Back key is pressed, the calculator unplugged or the * USB core soft-disconnected. */ Ion::Keyboard::Key exitKey = Ion::Keyboard::Key::Back; diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index 69370c0cb..2fdc9b5e1 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -17,500 +17,500 @@ namespace USB { static inline uint32_t minUint32T(uint32_t x, uint32_t y) { return x < y ? x : y; } void DFUInterface::StatusData::push(Channel *c) const { - c->push(m_bStatus); - c->push(m_bwPollTimeout[2]); - c->push(m_bwPollTimeout[1]); - c->push(m_bwPollTimeout[0]); - c->push(m_bState); - c->push(m_iString); + c->push(m_bStatus); + c->push(m_bwPollTimeout[2]); + c->push(m_bwPollTimeout[1]); + c->push(m_bwPollTimeout[0]); + c->push(m_bState); + c->push(m_iString); } void DFUInterface::StateData::push(Channel *c) const { - c->push(m_bState); + c->push(m_bState); } void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t)DFURequest::Download) { - // Handle a download request - if (request->wValue() == 0) { - // The request is a special command - switch (transferBuffer[0]) { - case (uint8_t)DFUDownloadCommand::SetAddressPointer: - setAddressPointerCommand(request, transferBuffer, *transferBufferLength); - return; - case (uint8_t)DFUDownloadCommand::Erase: - eraseCommand(transferBuffer, *transferBufferLength); - return; - default: - m_state = State::dfuERROR; - m_status = Status::errSTALLEDPKT; - return; - } - } - if (request->wValue() == 1) { - m_ep0->stallTransaction(); - return; - } - if (request->wLength() > 0) { - // The request is a "real" download. Compute the writing address. - m_writeAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; - - // Store the received data until we copy it on the flash. - memcpy(m_largeBuffer, transferBuffer, *transferBufferLength); - m_largeBufferLength = *transferBufferLength; - m_state = State::dfuDNLOADSYNC; - } + if (request->bRequest() == (uint8_t)DFURequest::Download) { + // Handle a download request + if (request->wValue() == 0) { + // The request is a special command + switch (transferBuffer[0]) { + case (uint8_t)DFUDownloadCommand::SetAddressPointer: + setAddressPointerCommand(request, transferBuffer, *transferBufferLength); + return; + case (uint8_t)DFUDownloadCommand::Erase: + eraseCommand(transferBuffer, *transferBufferLength); + return; + default: + m_state = State::dfuERROR; + m_status = Status::errSTALLEDPKT; + return; + } } + if (request->wValue() == 1) { + m_ep0->stallTransaction(); + return; + } + if (request->wLength() > 0) { + // The request is a "real" download. Compute the writing address. + m_writeAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; + + // Store the received data until we copy it on the flash. + memcpy(m_largeBuffer, transferBuffer, *transferBufferLength); + m_largeBufferLength = *transferBufferLength; + m_state = State::dfuDNLOADSYNC; + } + } } void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t)DFURequest::GetStatus) { - // Do any needed action after the GetStatus request. - if (m_state == State::dfuMANIFEST) { - if (m_dfuLevel == 1 && m_isFirstExternalFlash && !m_isInternalLocked) { - return; - } - /* If we leave the DFU and reset immediately, dfu-util outputs an error: - * "File downloaded successfully - * dfu-util: Error during download get_status" - * If we sleep 1us here, there is no error. We put 1ms for security. - * This error might be due to the USB connection being cut too soon after - * the last USB exchange, so the host does not have time to process the - * answer received for the last GetStatus request. */ - Ion::Timing::msleep(1); - // Leave DFU routine: Leave DFU, reset device, jump to application code - leaveDFUAndReset(); - } else if (m_state == State::dfuDNBUSY) { - m_state = State::dfuDNBUSY; - if (m_largeBufferLength != 0) { - // Here, copy the data from the transfer buffer to the flash memory - writeOnMemory(); - } - changeAddressPointerIfNeeded(); - eraseMemoryIfNeeded(); - m_state = State::dfuDNLOADIDLE; - } + if (request->bRequest() == (uint8_t)DFURequest::GetStatus) { + // Do any needed action after the GetStatus request. + if (m_state == State::dfuMANIFEST) { + if (m_dfuLevel == 1 && m_isFirstExternalFlash && !m_isInternalLocked) { + return; + } + /* If we leave the DFU and reset immediately, dfu-util outputs an error: + * "File downloaded successfully + * dfu-util: Error during download get_status" + * If we sleep 1us here, there is no error. We put 1ms for security. + * This error might be due to the USB connection being cut too soon after + * the last USB exchange, so the host does not have time to process the + * answer received for the last GetStatus request. */ + Ion::Timing::msleep(1); + // Leave DFU routine: Leave DFU, reset device, jump to application code + leaveDFUAndReset(); + } else if (m_state == State::dfuDNBUSY) { + m_state = State::dfuDNBUSY; + if (m_largeBufferLength != 0) { + // Here, copy the data from the transfer buffer to the flash memory + writeOnMemory(); + } + changeAddressPointerIfNeeded(); + eraseMemoryIfNeeded(); + m_state = State::dfuDNLOADIDLE; } + } } bool DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { - if (Interface::processSetupInRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength)) { - return true; - } - switch (request->bRequest()) { - case (uint8_t)DFURequest::Detach: - m_device->detach(); - return true; - case (uint8_t)DFURequest::Download: - return processDownloadRequest(request->wLength(), transferBufferLength); - case (uint8_t)DFURequest::Upload: - return processUploadRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::GetStatus: - return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::ClearStatus: - return clearStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::GetState: - return getState(transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::Abort: - return dfuAbort(transferBufferLength); - } - return false; + if (Interface::processSetupInRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength)) { + return true; + } + switch (request->bRequest()) { + case (uint8_t)DFURequest::Detach: + m_device->detach(); + return true; + case (uint8_t)DFURequest::Download: + return processDownloadRequest(request->wLength(), transferBufferLength); + case (uint8_t)DFURequest::Upload: + return processUploadRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength); + case (uint8_t)DFURequest::GetStatus: + return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); + case (uint8_t)DFURequest::ClearStatus: + return clearStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); + case (uint8_t)DFURequest::GetState: + return getState(transferBuffer, transferBufferLength, transferBufferMaxLength); + case (uint8_t)DFURequest::Abort: + return dfuAbort(transferBufferLength); + } + return false; } bool DFUInterface::processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength) { - if (m_state != State::dfuIDLE && m_state != State::dfuDNLOADIDLE) { - m_state = State::dfuERROR; - m_status = Status::errNOTDONE; - m_ep0->stallTransaction(); - return false; - } - if (wLength == 0) { - // Leave DFU routine: Reset the device and jump to application code - m_state = State::dfuMANIFESTSYNC; - } else { - // Prepare to receive the download data - m_ep0->clearForOutTransactions(wLength); - m_state = State::dfuDNLOADSYNC; - } - return true; + if (m_state != State::dfuIDLE && m_state != State::dfuDNLOADIDLE) { + m_state = State::dfuERROR; + m_status = Status::errNOTDONE; + m_ep0->stallTransaction(); + return false; + } + if (wLength == 0) { + // Leave DFU routine: Reset the device and jump to application code + m_state = State::dfuMANIFESTSYNC; + } else { + // Prepare to receive the download data + m_ep0->clearForOutTransactions(wLength); + m_state = State::dfuDNLOADSYNC; + } + return true; } bool DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { - if (m_state != State::dfuIDLE && m_state != State::dfuUPLOADIDLE) { - m_ep0->stallTransaction(); - return false; - } - if (request->wValue() == 0) { - /* The host requests to read the commands supported by the bootloader. After - * receiving this command, the device should returns N bytes representing - * the command codes for : - * Get command / Set Address Pointer / Erase / Read Unprotect - * We no not need it for now. */ - return false; - } else if (request->wValue() == 1) { - m_ep0->stallTransaction(); - return false; - } else { - /* We decided to never protect Read operation. Else we would have to check - * here it is not protected before reading. */ + if (m_state != State::dfuIDLE && m_state != State::dfuUPLOADIDLE) { + m_ep0->stallTransaction(); + return false; + } + if (request->wValue() == 0) { + /* The host requests to read the commands supported by the bootloader. After + * receiving this command, the device should returns N bytes representing + * the command codes for : + * Get command / Set Address Pointer / Erase / Read Unprotect + * We no not need it for now. */ + return false; + } else if (request->wValue() == 1) { + m_ep0->stallTransaction(); + return false; + } else { + /* We decided to never protect Read operation. Else we would have to check + * here it is not protected before reading. */ - // Compute the reading address - uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; - // Copy the requested memory zone into the transfer buffer. - uint16_t copySize = minUint32T(transferBufferMaxLength, request->wLength()); - memcpy(transferBuffer, (void *)readAddress, copySize); - *transferBufferLength = copySize; - } - m_state = State::dfuUPLOADIDLE; - return true; + // Compute the reading address + uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; + // Copy the requested memory zone into the transfer buffer. + uint16_t copySize = minUint32T(transferBufferMaxLength, request->wLength()); + memcpy(transferBuffer, (void *)readAddress, copySize); + *transferBufferLength = copySize; + } + m_state = State::dfuUPLOADIDLE; + return true; } void DFUInterface::setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength) { - assert(transferBufferLength == 5); - // Compute the new address but change it after the next getStatus request. - m_potentialNewAddressPointer = transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); - m_state = State::dfuDNLOADSYNC; + assert(transferBufferLength == 5); + // Compute the new address but change it after the next getStatus request. + m_potentialNewAddressPointer = transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); + m_state = State::dfuDNLOADSYNC; } void DFUInterface::changeAddressPointerIfNeeded() { - if (m_potentialNewAddressPointer == 0) { - // There was no address change waiting. - return; - } - // If there is a new address pointer waiting, change the pointer address. - m_addressPointer = m_potentialNewAddressPointer; - m_potentialNewAddressPointer = 0; - m_state = State::dfuDNLOADIDLE; - m_status = Status::OK; + if (m_potentialNewAddressPointer == 0) { + // There was no address change waiting. + return; + } + // If there is a new address pointer waiting, change the pointer address. + m_addressPointer = m_potentialNewAddressPointer; + m_potentialNewAddressPointer = 0; + m_state = State::dfuDNLOADIDLE; + m_status = Status::OK; } void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength) { - /* We determine whether the commands asks for a mass erase or which sector to + /* We determine whether the commands asks for a mass erase or which sector to * erase. The erase must be done after the next getStatus request. */ - m_state = State::dfuDNLOADSYNC; + m_state = State::dfuDNLOADSYNC; - if (transferBufferLength == 1) { - // Mass erase - m_erasePage = Flash::TotalNumberOfSectors(); - return; - } + if (transferBufferLength == 1) { + // Mass erase + m_erasePage = Flash::TotalNumberOfSectors(); + return; + } - // Sector erase - assert(transferBufferLength == 5); + // Sector erase + assert(transferBufferLength == 5); - m_eraseAddress = transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); + m_eraseAddress = transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); - m_erasePage = Flash::SectorAtAddress(m_eraseAddress); - if (m_erasePage < 0) { - // Unrecognized sector - m_state = State::dfuERROR; - m_status = Status::errTARGET; - } + m_erasePage = Flash::SectorAtAddress(m_eraseAddress); + if (m_erasePage < 0) { + // Unrecognized sector + m_state = State::dfuERROR; + m_status = Status::errTARGET; + } } void DFUInterface::eraseMemoryIfNeeded() { - if (m_erasePage < 0) { - return; - } - willErase(); - if ((m_eraseAddress >= k_ExternalBorderAddress && m_eraseAddress < ExternalFlash::Config::EndAddress) || m_dfuUnlocked) { - int32_t order = Flash::SectorAtAddress(m_eraseAddress); - Flash::EraseSector(order); - } - m_state = State::dfuDNLOADIDLE; - m_status = Status::OK; - m_erasePage = -1; + if (m_erasePage < 0) { + return; + } + willErase(); + if ((m_eraseAddress >= k_ExternalBorderAddress && m_eraseAddress < ExternalFlash::Config::EndAddress) || m_dfuUnlocked) { + int32_t order = Flash::SectorAtAddress(m_eraseAddress); + Flash::EraseSector(order); + } + m_state = State::dfuDNLOADIDLE; + m_status = Status::OK; + m_erasePage = -1; } void DFUInterface::writeOnMemory() { - if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) { - // Write on SRAM - // FIXME We should check that we are not overriding the current instructions. - memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength); - reset_custom_vars(); // On reset les vars car la ram n'a pas de secteur à effacer - } else if (Flash::SectorAtAddress(m_writeAddress) >= 0) { - if (m_dfuLevel == 2) { - m_largeBufferLength = 0; - m_state = State::dfuERROR; - m_status = Status::errWRITE; - return; - } + if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) { + // Write on SRAM + // FIXME We should check that we are not overriding the current instructions. + memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength); + reset_custom_vars(); // On reset les vars car la ram n'a pas de secteur à effacer + } else if (Flash::SectorAtAddress(m_writeAddress) >= 0) { + if (m_dfuLevel == 2) { + m_largeBufferLength = 0; + m_state = State::dfuERROR; + m_status = Status::errWRITE; + return; + } - int current_memory_flashed; - if (m_writeAddress >= InternalFlash::Config::StartAddress && m_writeAddress <= InternalFlash::Config::EndAddress) { - if (m_isInternalLocked && !m_dfuUnlocked) // On vérifie si l'external a été flash - { - m_largeBufferLength = 0; - m_state = State::dfuERROR; - m_status = Status::errTARGET; - leaveDFUAndReset(false); // Numworks flash l'internal avant donc on exit pour afficher le message - return; - } - current_memory_flashed = 0; - - //on écrit dans la mémoire interne - if (m_isFirstInternalFlash && !m_dfuUnlocked) { - m_temp_is_valid = true; - for (int i = 0; i < 4; i++) { - if (magik[i] != m_largeBuffer[magik_adrs + i]) { - m_temp_is_valid = false; - break; - } - } - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - m_state = State::dfuERROR; - m_status = Status::errVERIFY; - //leaveDFUAndReset(); On ne leave plus sinon on fait crash la calc si il n'y a que la partie ext. - return; - } else { - m_isFirstInternalFlash = false; - } - } - } else { - current_memory_flashed = 1; - // Nous écrivons la partie external os - if (m_writeAddress < k_ExternalBorderAddress && m_isFirstExternalFlash && !m_dfuUnlocked) // On vérifie si on installe des apps ext - { - // if (m_dfuLevel == 1 && m_isInternalLocked) { - // m_largeBufferLength = 0; - // m_state = State::dfuERROR; - // m_status = Status::errTARGET; - // return; - // } - if (m_dfuLevel == 0) { - // Partie moche du code parce que je n'arrivais pas à compil avec 3 boucles for sous msys - int adress_magik = magik_ext_adrs[0]; - m_temp_is_valid = external_magik[0] == m_largeBuffer[adress_magik]; - m_largeBuffer[adress_magik] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[1] == m_largeBuffer[adress_magik + 1]; - m_largeBuffer[adress_magik + 1] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[2] == m_largeBuffer[adress_magik + 2]; - m_largeBuffer[adress_magik + 2] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[3] == m_largeBuffer[adress_magik + 3]; - m_largeBuffer[adress_magik + 3] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - adress_magik = magik_ext_adrs[1]; - - m_temp_is_valid = external_magik[5] == m_largeBuffer[adress_magik]; - m_largeBuffer[adress_magik] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[6] == m_largeBuffer[adress_magik + 1]; - m_largeBuffer[adress_magik + 1] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[7] == m_largeBuffer[adress_magik + 2]; - m_largeBuffer[adress_magik + 2] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[8] == m_largeBuffer[adress_magik + 3]; - m_largeBuffer[adress_magik + 3] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - adress_magik = magik_ext_adrs[2]; - m_temp_is_valid = true; - - m_temp_is_valid = external_magik[0] == m_largeBuffer[adress_magik]; - m_largeBuffer[adress_magik] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[1] == m_largeBuffer[adress_magik + 1]; - m_largeBuffer[adress_magik + 1] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[2] == m_largeBuffer[adress_magik + 2]; - m_largeBuffer[adress_magik + 2] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[3] == m_largeBuffer[adress_magik + 3]; - m_largeBuffer[adress_magik + 3] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - - m_temp_is_valid = external_magik[4] == m_largeBuffer[adress_magik + 4]; - m_largeBuffer[adress_magik + 4] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - m_temp_is_valid = external_magik[5] == m_largeBuffer[adress_magik + 5]; - m_largeBuffer[adress_magik + 5] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - m_temp_is_valid = external_magik[6] == m_largeBuffer[adress_magik + 6]; - m_largeBuffer[adress_magik + 6] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - m_temp_is_valid = external_magik[7] == m_largeBuffer[adress_magik + 7]; - m_largeBuffer[adress_magik + 7] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } - m_temp_is_valid = external_magik[8] == m_largeBuffer[adress_magik + 8]; - m_largeBuffer[adress_magik + 8] = 0xff; - - if (!m_temp_is_valid) { - m_largeBufferLength = 0; - leaveDFUAndReset(false); - return; - } else { - m_isFirstExternalFlash = false; - m_isInternalLocked = false; - } - } else { - m_isFirstExternalFlash = false; - m_isInternalLocked = false; - } - } - } - if (m_last_memoryFlashed >= 0 && current_memory_flashed != m_last_memoryFlashed) { - m_last_memoryFlashed = -1; - } - - m_erasePage = Flash::SectorAtAddress(m_writeAddress); - - //On vérifie qu'on a pas déjà effacé le secteur et si ce n'est pas un secteur external déjà effacé - if ((m_last_memoryFlashed < 0 || m_erasePage != m_lastPageErased) && m_writeAddress < k_ExternalBorderAddress && !m_dfuUnlocked) { - Flash::EraseSector(m_erasePage); - m_last_memoryFlashed = current_memory_flashed; - } - - m_lastPageErased = m_erasePage; - m_erasePage = -1; - - Ion::Timing::msleep(1); - Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); - } else { - // Invalid write address + int current_memory_flashed; + if (m_writeAddress >= InternalFlash::Config::StartAddress && m_writeAddress <= InternalFlash::Config::EndAddress) { + if (m_isInternalLocked && !m_dfuUnlocked) // On vérifie si l'external a été flash + { m_largeBufferLength = 0; m_state = State::dfuERROR; m_status = Status::errTARGET; + leaveDFUAndReset(false); // Numworks flash l'internal avant donc on exit pour afficher le message return; + } + current_memory_flashed = 0; + + //on écrit dans la mémoire interne + if (m_isFirstInternalFlash && !m_dfuUnlocked) { + m_temp_is_valid = true; + for (int i = 0; i < 4; i++) { + if (magik[i] != m_largeBuffer[magik_adrs + i]) { + m_temp_is_valid = false; + break; + } + } + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + m_state = State::dfuERROR; + m_status = Status::errVERIFY; + //leaveDFUAndReset(); On ne leave plus sinon on fait crash la calc si il n'y a que la partie ext. + return; + } else { + m_isFirstInternalFlash = false; + } + } + } else { + current_memory_flashed = 1; + // Nous écrivons la partie external os + if (m_writeAddress < k_ExternalBorderAddress && m_isFirstExternalFlash && !m_dfuUnlocked) // On vérifie si on installe des apps ext + { + // if (m_dfuLevel == 1 && m_isInternalLocked) { + // m_largeBufferLength = 0; + // m_state = State::dfuERROR; + // m_status = Status::errTARGET; + // return; + // } + if (m_dfuLevel == 0) { + // Partie moche du code parce que je n'arrivais pas à compil avec 3 boucles for sous msys + int adress_magik = magik_ext_adrs[0]; + m_temp_is_valid = external_magik[0] == m_largeBuffer[adress_magik]; + m_largeBuffer[adress_magik] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[1] == m_largeBuffer[adress_magik + 1]; + m_largeBuffer[adress_magik + 1] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[2] == m_largeBuffer[adress_magik + 2]; + m_largeBuffer[adress_magik + 2] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[3] == m_largeBuffer[adress_magik + 3]; + m_largeBuffer[adress_magik + 3] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + adress_magik = magik_ext_adrs[1]; + + m_temp_is_valid = external_magik[5] == m_largeBuffer[adress_magik]; + m_largeBuffer[adress_magik] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[6] == m_largeBuffer[adress_magik + 1]; + m_largeBuffer[adress_magik + 1] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[7] == m_largeBuffer[adress_magik + 2]; + m_largeBuffer[adress_magik + 2] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[8] == m_largeBuffer[adress_magik + 3]; + m_largeBuffer[adress_magik + 3] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + adress_magik = magik_ext_adrs[2]; + m_temp_is_valid = true; + + m_temp_is_valid = external_magik[0] == m_largeBuffer[adress_magik]; + m_largeBuffer[adress_magik] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[1] == m_largeBuffer[adress_magik + 1]; + m_largeBuffer[adress_magik + 1] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[2] == m_largeBuffer[adress_magik + 2]; + m_largeBuffer[adress_magik + 2] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[3] == m_largeBuffer[adress_magik + 3]; + m_largeBuffer[adress_magik + 3] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + + m_temp_is_valid = external_magik[4] == m_largeBuffer[adress_magik + 4]; + m_largeBuffer[adress_magik + 4] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + m_temp_is_valid = external_magik[5] == m_largeBuffer[adress_magik + 5]; + m_largeBuffer[adress_magik + 5] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + m_temp_is_valid = external_magik[6] == m_largeBuffer[adress_magik + 6]; + m_largeBuffer[adress_magik + 6] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + m_temp_is_valid = external_magik[7] == m_largeBuffer[adress_magik + 7]; + m_largeBuffer[adress_magik + 7] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } + m_temp_is_valid = external_magik[8] == m_largeBuffer[adress_magik + 8]; + m_largeBuffer[adress_magik + 8] = 0xff; + + if (!m_temp_is_valid) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; + } else { + m_isFirstExternalFlash = false; + m_isInternalLocked = false; + } + } else { + m_isFirstExternalFlash = false; + m_isInternalLocked = false; + } + } } - // Reset the buffer length + if (m_last_memoryFlashed >= 0 && current_memory_flashed != m_last_memoryFlashed) { + m_last_memoryFlashed = -1; + } + + m_erasePage = Flash::SectorAtAddress(m_writeAddress); + + //On vérifie qu'on a pas déjà effacé le secteur et si ce n'est pas un secteur external déjà effacé + if ((m_last_memoryFlashed < 0 || m_erasePage != m_lastPageErased) && m_writeAddress < k_ExternalBorderAddress && !m_dfuUnlocked) { + Flash::EraseSector(m_erasePage); + m_last_memoryFlashed = current_memory_flashed; + } + + m_lastPageErased = m_erasePage; + m_erasePage = -1; + + Ion::Timing::msleep(1); + Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); + } else { + // Invalid write address m_largeBufferLength = 0; - // Change the interface state and status - m_state = State::dfuDNLOADIDLE; - m_status = Status::OK; + m_state = State::dfuERROR; + m_status = Status::errTARGET; + return; + } + // Reset the buffer length + m_largeBufferLength = 0; + // Change the interface state and status + m_state = State::dfuDNLOADIDLE; + m_status = Status::OK; } bool DFUInterface::getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { - // Change the status if needed - if (m_state == State::dfuMANIFESTSYNC) { - m_state = State::dfuMANIFEST; - } else if (m_state == State::dfuDNLOADSYNC) { - m_state = State::dfuDNBUSY; - } - // Copy the status on the TxFifo - *transferBufferLength = StatusData(m_status, m_state).copy(transferBuffer, transferBufferMaxLength); - return true; + // Change the status if needed + if (m_state == State::dfuMANIFESTSYNC) { + m_state = State::dfuMANIFEST; + } else if (m_state == State::dfuDNLOADSYNC) { + m_state = State::dfuDNBUSY; + } + // Copy the status on the TxFifo + *transferBufferLength = StatusData(m_status, m_state).copy(transferBuffer, transferBufferMaxLength); + return true; } bool DFUInterface::clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { - m_status = Status::OK; - m_state = State::dfuIDLE; - return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); + m_status = Status::OK; + m_state = State::dfuIDLE; + return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); } bool DFUInterface::getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize) { - *transferBufferLength = StateData(m_state).copy(transferBuffer, maxSize); - return true; + *transferBufferLength = StateData(m_state).copy(transferBuffer, maxSize); + return true; } bool DFUInterface::dfuAbort(uint16_t *transferBufferLength) { - m_status = Status::OK; - m_state = State::dfuIDLE; - *transferBufferLength = 0; - return true; + m_status = Status::OK; + m_state = State::dfuIDLE; + *transferBufferLength = 0; + return true; } void DFUInterface::leaveDFUAndReset(bool do_reset) { - reset_custom_vars(); - m_isInternalLocked = true; - m_isFirstInternalFlash = true; - m_isFirstExternalFlash = true; - m_device->setResetOnDisconnect(do_reset); - m_device->detach(); + reset_custom_vars(); + m_isInternalLocked = true; + m_isFirstInternalFlash = true; + m_isFirstExternalFlash = true; + m_device->setResetOnDisconnect(do_reset); + m_device->detach(); } } // namespace USB diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index 7d4ce8a7d..621c38a4c 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -13,212 +13,197 @@ namespace Ion { - namespace Device +namespace Device +{ +namespace USB +{ + +class DFUInterface : public Interface { + +public: + DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting): + Interface(ep0), + m_device(device), + m_status(Status::OK), + m_state(State::dfuIDLE), + m_addressPointer(0), + m_potentialNewAddressPointer(0), + m_erasePage(-1), + m_largeBuffer{0}, + m_largeBufferLength(0), + m_writeAddress(0), + m_eraseAddress(0), + m_bInterfaceAlternateSetting(bInterfaceAlternateSetting), + m_lastErasedPage(-1), + m_isErasingAndWriting(false), + m_isTemporaryUnlocked(false), + m_haveAlreadyFlashedExternal(false), + m_dfuUnlocked(false), + m_dfuLevel(0) { - namespace USB + + } + uint32_t addressPointer() const { return m_addressPointer; } + void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; + void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; + bool isErasingAndWriting() const { return m_isErasingAndWriting; } + void unlockDfu() { m_dfuUnlocked = true; }; + void setLevel(uint8_t lvl) { m_dfuLevel = lvl; } + +protected: + void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { + assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); + } + uint8_t getActiveInterfaceAlternative() override { + return m_bInterfaceAlternateSetting; + } + bool processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) override; + +private: + // DFU Request Codes + enum class DFURequest { + Detach = 0, + Download = 1, + Upload = 2, + GetStatus = 3, + ClearStatus = 4, + GetState = 5, + Abort = 6 + }; + + // DFU Download Commmand Codes + enum class DFUDownloadCommand { + GetCommand = 0x00, + SetAddressPointer = 0x21, + Erase = 0x41, + ReadUnprotect = 0x92 + }; + + enum class Status : uint8_t { + OK = 0x00, + errTARGET = 0x01, + errFILE = 0x02, + errWRITE = 0x03, + errERASE = 0x04, + errCHECK_ERASED = 0x05, + errPROG = 0x06, + errVERIFY = 0x07, + errADDRESS = 0x08, + errNOTDONE = 0x09, + errFIRMWARE = 0x0A, + errVENDOR = 0x0B, + errUSBR = 0x0C, + errPOR = 0x0D, + errUNKNOWN = 0x0E, + errSTALLEDPKT = 0x0F + }; + + enum class State : uint8_t { + appIDLE = 0, + appDETACH = 1, + dfuIDLE = 2, + dfuDNLOADSYNC = 3, + dfuDNBUSY = 4, + dfuDNLOADIDLE = 5, + dfuMANIFESTSYNC = 6, + dfuMANIFEST = 7, + dfuMANIFESTWAITRESET = 8, + dfuUPLOADIDLE = 9, + dfuERROR = 10 + }; + + class StatusData : public Streamable { + public: + StatusData(Status status, State state, uint32_t pollTimeout = 10): + /* We put a default pollTimeout value of 1ms: if the device is busy, the + * host has to wait 1ms before sending a getStatus Request. */ + m_bStatus((uint8_t)status), + m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), uint8_t(pollTimeout & 0xFF)}, + m_bState((uint8_t)state), + m_iString(0) { + } + protected: + void push(Channel * c) const override; + private: + uint8_t m_bStatus; // Status resulting from the execution of the most recent request + uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits + uint8_t m_bState; // State of the device immediately following transmission of this response + uint8_t m_iString; + }; - class DFUInterface : public Interface - { + class StateData : public Streamable + { + public: + StateData(State state) : m_bState((uint8_t)state) {} + protected: + void push(Channel *c) const override; + private: + uint8_t m_bState; // Current state of the device + }; - public: - DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : Interface(ep0), - m_device(device), - m_status(Status::OK), - m_state(State::dfuIDLE), - m_addressPointer(0), - m_potentialNewAddressPointer(0), - m_erasePage(-1), - m_largeBuffer{0}, - m_largeBufferLength(0), - m_writeAddress(0), - m_eraseAddress(0), - m_bInterfaceAlternateSetting(bInterfaceAlternateSetting), - m_isErasingAndWriting(false), - m_isFirstInternalFlash(true), - m_temp_is_valid(false), - m_isInternalLocked(true), - m_isFirstExternalFlash(true), - m_last_memoryFlashed(-1), - m_lastPageErased(-1), - m_dfuUnlocked(false), - m_dfuLevel(0) - { - } - uint32_t addressPointer() const { return m_addressPointer; } - void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; - void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; - bool isErasingAndWriting() const { return m_isErasingAndWriting; } - void unlockDfu() {m_dfuUnlocked = true;}; - void setLevel(int lvl) {m_dfuLevel = lvl; } - - protected: - void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override - { - assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); - } - uint8_t getActiveInterfaceAlternative() override - { - return m_bInterfaceAlternateSetting; - } - bool processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) override; - - private: - // DFU Request Codes - enum class DFURequest - { - Detach = 0, - Download = 1, - Upload = 2, - GetStatus = 3, - ClearStatus = 4, - GetState = 5, - Abort = 6 - }; - - // DFU Download Commmand Codes - enum class DFUDownloadCommand - { - GetCommand = 0x00, - SetAddressPointer = 0x21, - Erase = 0x41, - ReadUnprotect = 0x92 - }; - - enum class Status : uint8_t - { - OK = 0x00, - errTARGET = 0x01, - errFILE = 0x02, - errWRITE = 0x03, - errERASE = 0x04, - errCHECK_ERASED = 0x05, - errPROG = 0x06, - errVERIFY = 0x07, - errADDRESS = 0x08, - errNOTDONE = 0x09, - errFIRMWARE = 0x0A, - errVENDOR = 0x0B, - errUSBR = 0x0C, - errPOR = 0x0D, - errUNKNOWN = 0x0E, - errSTALLEDPKT = 0x0F - }; - - enum class State : uint8_t - { - appIDLE = 0, - appDETACH = 1, - dfuIDLE = 2, - dfuDNLOADSYNC = 3, - dfuDNBUSY = 4, - dfuDNLOADIDLE = 5, - dfuMANIFESTSYNC = 6, - dfuMANIFEST = 7, - dfuMANIFESTWAITRESET = 8, - dfuUPLOADIDLE = 9, - dfuERROR = 10 - }; - - class StatusData : public Streamable - { - public: - StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the - * host has to wait 1ms before sending a getStatus Request. */ - m_bStatus((uint8_t)status), - m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), uint8_t(pollTimeout & 0xFF)}, - m_bState((uint8_t)state), - m_iString(0) - { - } - - protected: - void push(Channel *c) const override; - - private: - uint8_t m_bStatus; // Status resulting from the execution of the most recent request - uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits - uint8_t m_bState; // State of the device immediately following transmission of this response - uint8_t m_iString; - }; - - class StateData : public Streamable - { - public: - StateData(State state) : m_bState((uint8_t)state) {} - - protected: - void push(Channel *c) const override; - - private: - uint8_t m_bState; // Current state of the device - }; - - /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is + /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is * linked with dfu.ld, so we cannot access the values. */ - constexpr static uint32_t k_sramStartAddress = 0x20000000; - constexpr static uint32_t k_sramEndAddress = 0x20040000; - constexpr static uint32_t k_ExternalBorderAddress = 0x90200000; + constexpr static uint32_t k_sramStartAddress = 0x20000000; + constexpr static uint32_t k_sramEndAddress = 0x20040000; + constexpr static uint32_t k_externalAppsBorderAddress = 0x90200000; - const static int magik_adrs = 0x1C4; - constexpr static int magik_ext_adrs[3] = {0x03, 0xb, 0x44f}; - constexpr static uint8_t magik[4] = {0xF0, 0x0D, 0xC0, 0xDE}; - constexpr static uint8_t external_magik[9] = {0x64, 0x6c, 0x31, 0x31, 0x23, 0x39, 0x38, 0x33, 0x35}; + const static int k_internalMagikPointer = 0x1C4; + constexpr static int k_externalMagikPointer = 0x44F; + constexpr static uint8_t k_internalMagik[4] = {0xF0, 0x0D, 0xC0, 0xDE}; + constexpr static uint8_t k_externalMagik[9] = {0x64, 0x6c, 0x31, 0x31, 0x23, 0x39, 0x38, 0x33, 0x35}; - // Download and upload - bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); - bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); - // Address pointer - void setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); - void changeAddressPointerIfNeeded(); - // Access memory - void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); - void eraseMemoryIfNeeded(); - void eraseMemoryIfNeededWithoutErasingAtAll(); - void writeOnMemory(); - void unlockFlashMemory(); - void lockFlashMemoryAndPurgeCaches(); - // Status - bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); - bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); - // State - bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); - // Abort - bool dfuAbort(uint16_t *transferBufferLength); - // Leave DFU - void leaveDFUAndReset(bool do_reset=true); - /* Erase and Write state. After starting the erase of flash memory, the user + // Download and upload + bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); + bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); + // Address pointer + void setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); + void changeAddressPointerIfNeeded(); + // Access memory + void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); + void eraseMemoryIfNeeded(); + void eraseMemoryIfNeededWithoutErasingAtAll(); + void writeOnMemory(); + void unlockFlashMemory(); + void lockFlashMemoryAndPurgeCaches(); + // Status + bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); + bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); + // State + bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); + // Abort + bool dfuAbort(uint16_t *transferBufferLength); + // Leave DFU + void leaveDFUAndReset(bool do_reset=true); + /* Erase and Write state. After starting the erase of flash memory, the user * can no longer leave DFU mode by pressing the Back key of the keyboard. This * way, we prevent the user from interrupting a software download. After every * software download, the calculator resets, which unlocks the "exit on * pressing back". */ - void willErase() { m_isErasingAndWriting = true; } - void reset_custom_vars() {m_temp_is_valid = true; m_last_memoryFlashed = -1; m_lastPageErased = -1;} + void willErase() { m_isErasingAndWriting = true; } + void resetProtectionVariables() { m_lastErasedPage = -1; m_isTemporaryUnlocked = false; m_haveAlreadyFlashedExternal = false; } - Device *m_device; - Status m_status; - State m_state; - uint32_t m_addressPointer; - uint32_t m_potentialNewAddressPointer; - int32_t m_erasePage; - uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; - uint16_t m_largeBufferLength; - uint32_t m_writeAddress; - uint32_t m_eraseAddress; - uint8_t m_bInterfaceAlternateSetting; - bool m_isErasingAndWriting; - bool m_isFirstInternalFlash; - bool m_temp_is_valid; - bool m_isInternalLocked; - bool m_isFirstExternalFlash; - int m_last_memoryFlashed; // -1: aucune; 0: internal; 1: external - int m_lastPageErased; // -1 par défaut - bool m_dfuUnlocked; - int m_dfuLevel; - }; + Device *m_device; + Status m_status; + State m_state; + uint32_t m_addressPointer; + uint32_t m_potentialNewAddressPointer; + int32_t m_erasePage; + uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; + uint16_t m_largeBufferLength; + uint32_t m_writeAddress; + uint32_t m_eraseAddress; + uint8_t m_bInterfaceAlternateSetting; + uint8_t m_lastErasedPage; + bool m_isErasingAndWriting; + bool m_isTemporaryUnlocked; + bool m_haveAlreadyFlashedExternal; + bool m_dfuUnlocked; + uint8_t m_dfuLevel; // 0: Upsilon only, 1: Omega-forked only, 2: No update +}; - } - } +} +} } #endif