diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index acf3feb383d..53f9242a79e 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -146,6 +146,10 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) { * We do it before switching to USB application to redraw the battery * pictogram. */ updateBatteryState(); + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { + //if in exam mode, do not switch to usb connected app + return true; + } if (switchTo(usbConnectedAppSnapshot())) { Ion::USB::DFU(); // Update LED when exiting DFU mode diff --git a/bootloader/boot.cpp b/bootloader/boot.cpp index 8970e12506c..7b1fd6d6159 100644 --- a/bootloader/boot.cpp +++ b/bootloader/boot.cpp @@ -71,10 +71,9 @@ __attribute__((noreturn)) void Boot::boot() { __attribute__ ((noreturn)) void Boot::bootloader() { for(;;) { + int modeFlash = 3; // Draw the interfaces and infos - Bootloader::Interface::draw(); - Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); - + Bootloader::Interface::draw(modeFlash); bool abortUSB = false; while (1) { uint64_t scan = Ion::Keyboard::scan(); @@ -84,16 +83,22 @@ __attribute__ ((noreturn)) void Boot::bootloader() { //allow to set bootmode with 1 and 2 if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::One)) { Bootloader::Boot::setMode(Bootloader::BootMode::SlotA); - Bootloader::Interface::draw(); - Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); + Bootloader::Interface::draw(modeFlash); Ion::Timing::msleep(100); } if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Two)) { Bootloader::Boot::setMode(Bootloader::BootMode::SlotB); - Bootloader::Interface::draw(); - Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); + Bootloader::Interface::draw(modeFlash); Ion::Timing::msleep(100); } + if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Plus)) { + modeFlash = modeFlash + 1; + if (modeFlash > 3) { + modeFlash = 1; + } + Ion::Timing::msleep(100); + Bootloader::Interface::draw(modeFlash); + } if (Ion::USB::isPlugged() && !abortUSB) { // Enable USB @@ -101,21 +106,14 @@ __attribute__ ((noreturn)) void Boot::bootloader() { Bootloader::Interface::drawMessageBox("USB Enabled", "Press Back to disable USB"); // Launch the DFU stack, allowing to press Back to quit and reset - Ion::USB::DFU(true); - //wait for usb to be unplugged or back to be pressed - while (Ion::USB::isPlugged() && scan != Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - scan = Ion::Keyboard::scan(); - Ion::Timing::msleep(100); - } - //cehck if usb is plugged + Ion::USB::DFU(true, modeFlash); + //check if usb is plugged if (Ion::USB::isPlugged()) { abortUSB = true; } // Disable USB Ion::USB::disable(); - Bootloader::Interface::draw(); - Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); - + Bootloader::Interface::draw(modeFlash); } //Prevent USB from launching after Back press diff --git a/bootloader/interface.cpp b/bootloader/interface.cpp index de86046c8ff..7e30efade25 100644 --- a/bootloader/interface.cpp +++ b/bootloader/interface.cpp @@ -53,12 +53,12 @@ void Interface::drawImage(KDContext* ctx, const Image* image, int offset) { ctx->fillRectWithPixels(bounds, pixelBuffer, nullptr); } -void Interface::draw() { +void Interface::draw(int currentUSB) { KDContext * ctx = KDIonContext::sharedContext(); ctx->fillRect(KDRect(0,0,320,240), KDColorBlack); drawImage(ctx, ImageStore::Computer, 70); - drawImage(ctx, ImageStore::Cable, 172); - + drawImage(ctx, ImageStore::Cable, 132); + drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); ctx->drawString("Slot A:", KDPoint(0, 0), KDFont::SmallFont, KDColorWhite, KDColorBlack); ctx->drawString("Slot B:", KDPoint(0, 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); ctx->drawString("Current:", KDPoint(0, 26), KDFont::SmallFont, KDColorWhite, KDColorBlack); @@ -86,19 +86,34 @@ void Interface::draw() { ctx->drawString(slot.userlandHeader()->version(), KDPoint(112, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack); } ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(168, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack); - } else { - if (slot.userland2Header()->isValid()) { - ctx->drawString("Epsilon", KDPoint(56, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); - ctx->drawString(slot.userland2Header()->version(), KDPoint(112, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); - ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(168, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); - } - else { - ctx->drawString("Invalid", KDPoint(56, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); - } + } + else { + if (slot.userland2Header()->isValid()) { + ctx->drawString("Epsilon", KDPoint(56, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + ctx->drawString(slot.userland2Header()->version(), KDPoint(112, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(168, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + } + else { + ctx->drawString("Invalid", KDPoint(56, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + } } } - + char* USBFlashVerbose = ""; + if (currentUSB == 1) { + USBFlashVerbose = "Slot A"; + } + else if (currentUSB == 2) { + USBFlashVerbose = "Slot B"; + } + else if (currentUSB == 3) { + USBFlashVerbose = "Slot A & B"; + } + //add USBFlashVerbose to USBFlashVerboseStatus + ctx->drawString("USB Flash Mode: ", KDPoint(0, 180), KDFont::SmallFont, KDColorWhite, KDColorBlack); + ctx->drawString(USBFlashVerbose, KDPoint(112, 180), KDFont::SmallFont, KDColorWhite, KDColorBlack); + ctx->drawString("Press (+) to switch mode", KDPoint(0, 193), KDFont::SmallFont, KDColorWhite, KDColorBlack); + ctx->drawString("2.0.6", KDPoint(260, 180), KDFont::LargeFont, KDColorRed, KDColorBlack); if (Bootloader::Slot::A().kernelHeader()->isValid()) { const char* version = Bootloader::Slot::A().kernelHeader()->version(); bool isExam = Bootloader::ExamMode::SlotsExamMode::FetchSlotExamMode(version, "A") > 0; diff --git a/bootloader/interface.h b/bootloader/interface.h index 7cd61329044..a2430c1f1c3 100644 --- a/bootloader/interface.h +++ b/bootloader/interface.h @@ -13,7 +13,7 @@ class Interface { static void drawImage(KDContext* ctx, const Image* image, int offset); public: - static void draw(); + static void draw(int currentUSB); static void drawMessageBox(const char* line1, const char* line2); }; diff --git a/bootloader/slot_exam_mode.cpp b/bootloader/slot_exam_mode.cpp index fc96b541998..5e3ced599cd 100644 --- a/bootloader/slot_exam_mode.cpp +++ b/bootloader/slot_exam_mode.cpp @@ -89,47 +89,48 @@ uint32_t SlotsExamMode::getSlotBEndExamAddress(int ExamVersion) { } uint8_t SlotsExamMode::FetchSlotExamMode(const char* version, const char* Slot) { - //get start and end from version and slot - uint32_t start = 0; - uint32_t end = 0; - if (Slot == "A") { - //if version under 16 get Old - if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) { - start = getSlotAStartExamAddress(0); +//get start and end from version and slot +uint32_t start = 0; +uint32_t end = 0; +if (Slot == "A") { + //if version under 16 get Old + if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) { + start = getSlotAStartExamAddress(0); end = getSlotAEndExamAddress(0); - } - //else get new - else { - start = getSlotAStartExamAddress(1); - end = getSlotAEndExamAddress(1); - } - } - else if (Slot == "B") { - //if version under 16 get Old - if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) { + } + //else get new + else { + start = getSlotAStartExamAddress(1); + end = getSlotAEndExamAddress(1); + } +} +else if (Slot == "B") { + //if version under 16 get Old + if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) { start = getSlotBStartExamAddress(0); end = getSlotBEndExamAddress(0); - } - //else get new - else { - start = getSlotBStartExamAddress(1); - end = getSlotBEndExamAddress(1); - } - } - - if (strcmp("15.9.0", version) >= 0) { - return examFetch15(start, end); - } else if (strcmp("16.9.0", version) > 0) { - return examFetch16(start, end); - } - else if (strcmp("19.0.0", version) > 0) { - return examFetch1718(start, end); } + //else get new else { - return examFetch19(start, end); + start = getSlotBStartExamAddress(1); + end = getSlotBEndExamAddress(1); } } +if (strcmp("15.9.0", version) >= 0) { + return examFetch15(start, end); +} +else if (strcmp("16.9.0", version) > 0) { + return examFetch16(start, end); +} +else if (strcmp("19.0.0", version) > 0) { + return examFetch1718(start, end); +} +else { + return examFetch19(start, end); +} +} + uint8_t SlotsExamMode::examFetch15(uint32_t start, uint32_t end) { uint32_t* persitence_start_32 = (uint32_t*)start; uint32_t* persitence_end_32 = (uint32_t*)end; @@ -186,11 +187,18 @@ uint8_t SlotsExamMode::examFetch19(uint32_t start, uint32_t end) { uint16_t* start16 = (uint16_t*)start; uint16_t* end16 = (uint16_t*)end; - while (start16 + 1 <= end16 && *start16 != 0xFFFF) { - start16++; - } - - return *(start16 - 1) >> 8; + for (uint16_t* i = end16 - 2; i > start16; i--) { + if (*i != 0xFFFF) { + uint8_t highByte = *i >> 8; + uint8_t lowByte = *i & 0xFF; + if (highByte > lowByte) { + return highByte; + } + else { + return lowByte; + } + } + } } diff --git a/bootloader/usb_desc.cpp b/bootloader/usb_desc.cpp index be49306000b..43927c0ceed 100644 --- a/bootloader/usb_desc.cpp +++ b/bootloader/usb_desc.cpp @@ -3,8 +3,14 @@ namespace Ion { namespace Device { namespace USB { -const char* stringDescriptor() { - return "@Flash/0x90000000/08*004Kg,01*032Kg,63*064Kg,64*064Kg"; +const char* stringDescriptor(int slot) { + if (slot == 1) { + return "@Flash/0x90000000/08*004Kg,01*032Kg,63*064Kg"; + } else if (slot == 2) { + return "@Flash/0x90400000/64*064Kg"; + } else if (slot == 3) { + return "@Flash/0x90000000/08*004Kg,01*032Kg,63*064Kg,64*064Kg"; + } } } diff --git a/build/config.mak b/build/config.mak index 638fe7b8d82..e85852d9893 100644 --- a/build/config.mak +++ b/build/config.mak @@ -5,7 +5,7 @@ DEBUG ?= 0 HOME_DISPLAY_EXTERNALS ?= 1 EPSILON_VERSION ?= 15.5.0 -OMEGA_VERSION ?= 2.0.5 +OMEGA_VERSION ?= 2.0.6 # OMEGA_USERNAME ?= N/A OMEGA_STATE ?= public EPSILON_APPS ?= calculation rpn graph code statistics probability solver atomic sequence regression settings external diff --git a/ion/include/ion/usb.h b/ion/include/ion/usb.h index e5760bb947a..d07fa073767 100644 --- a/ion/include/ion/usb.h +++ b/ion/include/ion/usb.h @@ -8,7 +8,7 @@ bool isPlugged(); bool isEnumerated(); // Speed-enumerated, to be accurate void clearEnumerationInterrupt(); -void DFU(bool exitWithKeyboard = true); +void DFU(bool exitWithKeyboard = true, int slot = 3); void enable(); void disable(); diff --git a/ion/src/device/shared/drivers/usb.h b/ion/src/device/shared/drivers/usb.h index 598aa4e9f16..a57adffc326 100644 --- a/ion/src/device/shared/drivers/usb.h +++ b/ion/src/device/shared/drivers/usb.h @@ -12,7 +12,7 @@ void initGPIO(); void shutdownGPIO(); void initOTG(); void shutdownOTG(); -const char* stringDescriptor(); +const char* stringDescriptor(int slot = 3); } } diff --git a/ion/src/device/shared/drivers/usb_desc.cpp b/ion/src/device/shared/drivers/usb_desc.cpp index 34ea8527ae8..1b2c2192890 100644 --- a/ion/src/device/shared/drivers/usb_desc.cpp +++ b/ion/src/device/shared/drivers/usb_desc.cpp @@ -6,7 +6,7 @@ namespace Ion { namespace Device { namespace USB { -const char* stringDescriptor() { +const char* stringDescriptor(int slot) { return Config::InterfaceStringDescriptor; } diff --git a/ion/src/device/shared/usb/calculator.cpp b/ion/src/device/shared/usb/calculator.cpp index 73d6bf5794e..47b82e5e6eb 100644 --- a/ion/src/device/shared/usb/calculator.cpp +++ b/ion/src/device/shared/usb/calculator.cpp @@ -7,10 +7,10 @@ namespace Ion { namespace Device { namespace USB { -void Calculator::PollAndReset(bool exitWithKeyboard) { +void Calculator::PollAndReset(bool exitWithKeyboard, int slot) { char serialNumber[Ion::Device::SerialNumber::Length+1]; Ion::Device::SerialNumber::copy(serialNumber); - Calculator c(serialNumber); + Calculator c(serialNumber, slot); /* Leave DFU mode if the Back key is pressed, the calculator unplugged or the * USB core soft-disconnected. */ diff --git a/ion/src/device/shared/usb/calculator.h b/ion/src/device/shared/usb/calculator.h index e5eaba3a467..14facc64f2e 100644 --- a/ion/src/device/shared/usb/calculator.h +++ b/ion/src/device/shared/usb/calculator.h @@ -26,11 +26,11 @@ namespace USB { class Calculator : public Device { public: - static void PollAndReset(bool exitWithKeyboard) + static void PollAndReset(bool exitWithKeyboard, int slot = 3) __attribute__((section(".dfu_entry_point"))) // Needed to pinpoint this symbol in the linker script __attribute__((used)) // Make sure this symbol is not discarded at link time ; // Return true if reset is needed - Calculator(const char * serialNumber) : + Calculator(const char * serialNumber, int slot = 3) : Device(&m_dfuInterface), m_deviceDescriptor( 0x0210, /* bcdUSB: USB Specification Number which the device complies @@ -95,7 +95,7 @@ class Calculator : public Device { m_manufacturerStringDescriptor("NumWorks"), m_productStringDescriptor("NumWorks Calculator"), m_serialNumberStringDescriptor(serialNumber), - m_interfaceStringDescriptor(stringDescriptor()), + m_interfaceStringDescriptor(stringDescriptor(slot)), //m_interfaceStringDescriptor("@SRAM/0x20000000/01*256Ke"), /* Switch to this descriptor to use dfu-util to write in the SRAM. * FIXME Should be an alternate Interface. */ diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index 2b98274b430..a05ba8052f8 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -23,34 +23,34 @@ void DFUInterface::StateData::push(Channel * c) const { } void DFUInterface::wholeDataReceivedCallback(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength) { - if (request->bRequest() == (uint8_t) DFURequest::Download) { + 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() == 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; + // 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; } } } diff --git a/ion/src/device/shared/usb/dfu_relocated.cpp b/ion/src/device/shared/usb/dfu_relocated.cpp index fb001cef1c4..56f7283793e 100644 --- a/ion/src/device/shared/usb/dfu_relocated.cpp +++ b/ion/src/device/shared/usb/dfu_relocated.cpp @@ -14,7 +14,7 @@ namespace USB { typedef void (*PollFunctionPointer)(bool exitWithKeyboard); -void DFU(bool exitWithKeyboard) { +void DFU(bool exitWithKeyboard, int slot) { Ion::updateSlotInfo(); /* DFU transfers can serve two purposes: diff --git a/ion/src/device/shared/usb/dfu_xip.cpp b/ion/src/device/shared/usb/dfu_xip.cpp index fd0447c3268..77f7209fdc4 100644 --- a/ion/src/device/shared/usb/dfu_xip.cpp +++ b/ion/src/device/shared/usb/dfu_xip.cpp @@ -4,9 +4,9 @@ namespace Ion { namespace USB { -void DFU(bool exitWithKeyboard) { +void DFU(bool exitWithKeyboard, int slot) { Ion::updateSlotInfo(); - Ion::Device::USB::Calculator::PollAndReset(exitWithKeyboard); + Ion::Device::USB::Calculator::PollAndReset(exitWithKeyboard, slot); } }