mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[usb | recovery] Improve code quality
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
4
apps/settings/base.universal.i18n
Normal file
4
apps/settings/base.universal.i18n
Normal file
@@ -0,0 +1,4 @@
|
||||
UsbSetting = "USB"
|
||||
USBDefaultLevelDesc = "L0"
|
||||
USBLowLevelDesc = "L1"
|
||||
USBParanoidLevelDesc = "L2"
|
||||
@@ -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)};
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define USB_USB_CONNECTED_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#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
|
||||
|
||||
|
||||
@@ -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
|
||||
$(PYTHON) build/device/secure_ext.py $(BUILD_DIR)/epsilon.onboarding.external.bin
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "isr.h"
|
||||
#include <drivers/battery.h>
|
||||
#include <drivers/cache.h>
|
||||
#include <drivers/external_flash.h>
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<uint8_t *>(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<uint8_t *>(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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user