rusEFI console to has "Erase via DFU" button #2250

This commit is contained in:
rusefillc 2021-11-23 16:12:39 -05:00
parent 7287d41467
commit a4a490fcb7
6 changed files with 82 additions and 50 deletions

View File

@ -22,6 +22,7 @@ public class PortDetector {
private final static Logging log = Logging.getLogging(PortDetector.class);
private static final NamedThreadFactory AUTO_DETECT_PORT = new NamedThreadFactory("AutoDetectPort");
public static final String AUTO = "auto";
/**
* Connect to all serial ports and find out which one respond first
@ -111,6 +112,6 @@ public class PortDetector {
}
public static boolean isAutoPort(String port) {
return port.toLowerCase().startsWith("auto");
return port.toLowerCase().startsWith(AUTO);
}
}

View File

@ -6,6 +6,7 @@ import com.rusefi.SignatureHelper;
import com.rusefi.autoupdate.Autoupdate;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.config.generated.Fields;
import com.rusefi.ui.StatusConsumer;
import javax.swing.*;
import java.io.IOException;
@ -16,7 +17,7 @@ import static com.rusefi.binaryprotocol.BinaryProtocol.sleep;
public class DfuHelper {
private static final String PREFIX = "rusefi_bundle";
public static void sendDfuRebootCommand(IoStream stream, StringBuilder messages) {
public static void sendDfuRebootCommand(IoStream stream, StatusConsumer messages) {
byte[] command = BinaryProtocol.getTextCommandBytes(Fields.CMD_REBOOT_DFU);
try {
stream.sendPacket(command);
@ -27,7 +28,7 @@ public class DfuHelper {
}
}
public static boolean sendDfuRebootCommand(JComponent parent, String signature, IoStream stream, StringBuilder messages) {
public static boolean sendDfuRebootCommand(JComponent parent, String signature, IoStream stream, StatusConsumer messages) {
RusEfiSignature s = SignatureHelper.parse(signature);
String bundleName = Autoupdate.readBundleFullName();
if (bundleName != null && s != null) {

View File

@ -2,4 +2,6 @@ package com.rusefi.ui;
public interface StatusConsumer {
void appendMsg(String s);
void append(String s);
}

View File

@ -11,6 +11,7 @@ import com.rusefi.io.IoStream;
import com.rusefi.io.serial.SerialIoStreamJSerialComm;
import com.rusefi.ui.StatusWindow;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.BufferedReader;
@ -40,46 +41,11 @@ public class DfuFlasher {
return;
}
String port = selectedItem.toString();
StringBuilder messages = new StringBuilder();
AtomicBoolean isSignatureValidated = new AtomicBoolean(true);
if (!PortDetector.isAutoPort(port)) {
messages.append("Using selected " + port + "\n");
IoStream stream = SerialIoStreamJSerialComm.openPort(port);
AtomicReference<String> signature = new AtomicReference<>();
new SerialAutoChecker(port, new CountDownLatch(1)).checkResponse(stream, new Function<SerialAutoChecker.CallbackContext, Void>() {
@Override
public Void apply(SerialAutoChecker.CallbackContext callbackContext) {
signature.set(callbackContext.getSignature());
return null;
}
});
if (signature.get() == null) {
JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI has not responded on selected " + port + "\n" +
"Maybe try automatic serial port detection?");
return;
}
boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, signature.get(), stream, messages);
isSignatureValidated.set(isSignatureValidatedLocal);
} else {
messages.append("Auto-detecting port...\n");
// instead of opening the just-detected port we execute the command using the same stream we used to discover port
// it's more reliable this way
port = PortDetector.autoDetectSerial(callbackContext -> {
boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, callbackContext.getSignature(), callbackContext.getStream(), messages);
isSignatureValidated.set(isSignatureValidatedLocal);
return null;
}).getSerialPort();
if (port == null) {
JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI serial port not detected");
return;
} else {
messages.append("Detected rusEFI on " + port + "\n");
}
}
StatusWindow wnd = new StatusWindow();
wnd.showFrame(appendBundleName("DFU status " + Launcher.CONSOLE_VERSION));
wnd.appendMsg(messages.toString());
StatusWindow wnd = createStatusWindow();
AtomicBoolean isSignatureValidated = rebootToDfu(parent, port, wnd);
if (isSignatureValidated == null) return;
if (isSignatureValidated.get()) {
if (!ProgramSelector.IS_WIN) {
wnd.appendMsg("Switched to DFU mode!");
@ -95,9 +61,55 @@ public class DfuFlasher {
}
}
public static void runDfuProgramming() {
@Nullable
public static AtomicBoolean rebootToDfu(JComponent parent, String port, StatusWindow wnd) {
AtomicBoolean isSignatureValidated = new AtomicBoolean(true);
if (!PortDetector.isAutoPort(port)) {
wnd.append("Using selected " + port + "\n");
IoStream stream = SerialIoStreamJSerialComm.openPort(port);
AtomicReference<String> signature = new AtomicReference<>();
new SerialAutoChecker(port, new CountDownLatch(1)).checkResponse(stream, new Function<SerialAutoChecker.CallbackContext, Void>() {
@Override
public Void apply(SerialAutoChecker.CallbackContext callbackContext) {
signature.set(callbackContext.getSignature());
return null;
}
});
if (signature.get() == null) {
JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI has not responded on selected " + port + "\n" +
"Maybe try automatic serial port detection?");
return null;
}
boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, signature.get(), stream, wnd);
isSignatureValidated.set(isSignatureValidatedLocal);
} else {
wnd.append("Auto-detecting port...\n");
// instead of opening the just-detected port we execute the command using the same stream we used to discover port
// it's more reliable this way
port = PortDetector.autoDetectSerial(callbackContext -> {
boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, callbackContext.getSignature(), callbackContext.getStream(), wnd);
isSignatureValidated.set(isSignatureValidatedLocal);
return null;
}).getSerialPort();
if (port == null) {
JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI serial port not detected");
return null;
} else {
wnd.append("Detected rusEFI on " + port + "\n");
}
}
return isSignatureValidated;
}
@NotNull
protected static StatusWindow createStatusWindow() {
StatusWindow wnd = new StatusWindow();
wnd.showFrame(appendBundleName("DFU status " + Launcher.CONSOLE_VERSION));
return wnd;
}
public static void runDfuProgramming() {
StatusWindow wnd = createStatusWindow();
ExecHelper.submitAction(() -> executeDFU(wnd), DfuFlasher.class + " thread");
}

View File

@ -1,6 +1,8 @@
package com.rusefi.maintenance;
import com.rusefi.autodetect.PortDetector;
import com.rusefi.autoupdate.AutoupdateUtil;
import com.rusefi.ui.StatusWindow;
import com.rusefi.ui.util.URLLabel;
import org.jetbrains.annotations.NotNull;
@ -16,6 +18,8 @@ public class ProgramSelector {
private static final String AUTO_DFU = "Auto DFU";
private static final String MANUAL_DFU = "Manual DFU";
private static final String DFU_SWITCH = "Switch to DFU";
private static final String DFU_ERASE = "Full Erase";
private static final String ST_LINK = "ST-LINK";
public static final boolean IS_WIN = System.getProperty("os.name").toLowerCase().contains("win");
@ -31,13 +35,15 @@ public class ProgramSelector {
mode.addItem(AUTO_DFU);
if (IS_WIN) {
mode.addItem(MANUAL_DFU);
mode.addItem(DFU_ERASE);
mode.addItem(ST_LINK);
}
mode.addItem(DFU_SWITCH);
controls.add(mode);
String persistedMode = getConfig().getRoot().getProperty(getClass().getSimpleName());
if (Arrays.asList(AUTO_DFU, MANUAL_DFU, ST_LINK).contains(persistedMode))
if (Arrays.asList(AUTO_DFU, MANUAL_DFU, ST_LINK, DFU_ERASE, DFU_SWITCH).contains(persistedMode))
mode.setSelectedItem(persistedMode);
JButton updateFirmware = new JButton("Update Firmware",
@ -51,16 +57,21 @@ public class ProgramSelector {
getConfig().getRoot().setProperty(getClass().getSimpleName(), selectedMode);
boolean isAutoDfu = selectedMode.equals(AUTO_DFU);
boolean isManualDfu = selectedMode.equals(MANUAL_DFU);
// todo: add ST-LINK no-assert mode
if (isAutoDfu) {
if (selectedMode.equals(AUTO_DFU)) {
DfuFlasher.doAutoDfu(comboPorts.getSelectedItem(), comboPorts);
} else if (isManualDfu) {
} else if (selectedMode.equals(MANUAL_DFU)) {
DfuFlasher.runDfuProgramming();
} else {
} else if (selectedMode.equals(ST_LINK)) {
// todo: add ST-LINK no-assert mode? or not?
FirmwareFlasher.doUpdateFirmware(FirmwareFlasher.IMAGE_FILE, updateFirmware);
} else if (selectedMode.equals(DFU_SWITCH)) {
StatusWindow wnd = DfuFlasher.createStatusWindow();
Object selected = comboPorts.getSelectedItem();
String port = selected == null ? PortDetector.AUTO : selected.toString();
DfuFlasher.rebootToDfu(comboPorts, port, wnd);
} else {
throw new IllegalArgumentException("How did you " + selectedMode);
}
}
});

View File

@ -72,6 +72,11 @@ public class StatusWindow implements StatusConsumer {
});
}
@Override
public void append(String s) {
appendMsg(s);
}
public void setStatus(String status) {
bottomStatusLabel.setText(status);
}