diff --git a/android/app/lib/dfu_java.jar b/android/app/lib/dfu_java.jar index 19039cfbfa..da44568c60 100644 Binary files a/android/app/lib/dfu_java.jar and b/android/app/lib/dfu_java.jar differ diff --git a/android/app/src/main/java/com/rusefi/app/rusEFI.java b/android/app/src/main/java/com/rusefi/app/rusEFI.java index 865f262002..9db40c962c 100644 --- a/android/app/src/main/java/com/rusefi/app/rusEFI.java +++ b/android/app/src/main/java/com/rusefi/app/rusEFI.java @@ -31,10 +31,14 @@ import android.widget.TextView; import com.hoho.android.usbserial.driver.UsbSerialDriver; import com.hoho.android.usbserial.driver.UsbSerialPort; -import com.hoho.android.usbserial.util.SerialInputOutputManager; import com.opensr5.Logger; +import com.rusefi.dfu.DfuCommmand; +import com.rusefi.dfu.DfuConnection; import com.rusefi.dfu.DfuImage; +import com.rusefi.dfu.DfuLogic; +import com.rusefi.dfu.FlashRange; import com.rusefi.dfu.android.DfuDeviceLocator; +import com.rusefi.dfu.commands.DfuCommandGetStatus; import com.rusefi.io.DfuHelper; import com.rusefi.shared.ConnectionAndMeta; import com.rusefi.shared.FileUtil; @@ -42,21 +46,31 @@ import com.rusefi.*; import java.io.File; import java.io.IOException; +import java.nio.ByteBuffer; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.Date; import java.util.List; -import java.util.concurrent.Executors; + +import static android.hardware.usb.UsbConstants.USB_DIR_IN; +import static android.hardware.usb.UsbConstants.USB_DIR_OUT; public class rusEFI extends Activity { private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; public static final String FILE = "rusefi_bundle_mre_f4_autoupdate.zip"; + private static final byte REQUEST_TYPE_CLASS = 32; + private static final byte RECIPIENT_INTERFACE = 0x01; + + + protected static final int DFU_DETACH_TIMEOUT = 1000; + /* UI elements */ private TextView mStatusView; private TextView mResultView; private UsbManager usbManager; + private String localDfuImageFileName; @Override protected void onCreate(Bundle savedInstanceState) { @@ -77,11 +91,11 @@ public class rusEFI extends Activity { final File localFolder = getExternalFilesDir(null); final String localFullFile = localFolder + File.separator + FILE; - final String localDfuName = localFolder + File.separator + "rusefi_mre_f4.dfu"; + localDfuImageFileName = localFolder + File.separator + "rusefi_mre_f4.dfu"; if (new File(localFullFile).exists()) { mResultView.append(FILE + " found!\n"); - uncompressFile(localFullFile, localFolder, localDfuName); + uncompressFile(localFullFile, localFolder, localDfuImageFileName); } else { mResultView.append(FILE + " not found!\n"); @@ -107,7 +121,7 @@ public class rusEFI extends Activity { mResultView.append("Downloaded! " + "\n"); } }); - uncompressFile(localFullFile, localFolder, localDfuName); + uncompressFile(localFullFile, localFolder, localDfuImageFileName); } catch (IOException | KeyManagementException | NoSuchAlgorithmException e) { mResultView.post(new Runnable() { @@ -125,25 +139,25 @@ public class rusEFI extends Activity { handleButton(); } - private void uncompressFile(final String localFullFile, final File localFolder, final String localDfuName) { + private void uncompressFile(final String localFullFile, final File localFolder, final String localDfuImageFileName) { final Listener onSuccess = new Listener() { @Override public void onResult(final Integer size) { mResultView.post(new Runnable() { @Override public void run() { - mResultView.append("File size: " + size + "\n"); + mResultView.append(localDfuImageFileName + " File size: " + size + "\n"); } }); DfuImage dfuImage = new DfuImage(); - dfuImage.read(localDfuName); + dfuImage.read(localDfuImageFileName); } }; new Thread(() -> { try { FileUtil.unzip(localFullFile, localFolder); - final int size = (int) new File(localDfuName).length(); + final int size = (int) new File(localDfuImageFileName).length(); onSuccess.onResult(size); } catch (final IOException e) { @@ -190,7 +204,7 @@ public class rusEFI extends Activity { List availableDrivers = AndroidSerial.findUsbSerial(usbManager); if (availableDrivers.isEmpty()) { mStatusView.setText("Not connected"); - mResultView.append("No serial devices " + new Date()); + mResultView.append("No serial devices " + new Date() + "\n"); return; } mStatusView.setText("rusEFI: " + availableDrivers.size() + " device(s)"); @@ -209,6 +223,7 @@ public class rusEFI extends Activity { port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); AndroidSerial serial = new AndroidSerial(port); + mResultView.append("Switching to DFU\n"); DfuHelper.sendDfuRebootCommand(serial, new StringBuilder(), Logger.CONSOLE); } catch (IOException e) { @@ -225,8 +240,73 @@ public class rusEFI extends Activity { } } - private DfuDeviceLocator.Result dfuUpdate(UsbDevice dfuDevice) { - return new DfuDeviceLocator().openDfu(usbManager, dfuDevice); + private void dfuUpdate(UsbDevice dfuDevice) { + mStatusView.setText("rusEFI: DFU detected"); + DfuDeviceLocator.Result dfu = new DfuDeviceLocator().openDfu(usbManager, dfuDevice); + + DfuImage dfuImage = new DfuImage(); + dfuImage.read(localDfuImageFileName); + mResultView.append("Image size " + dfuImage.getImageSize() + "\n"); + + DfuConnection c = new DfuConnection() { + @Override + public FlashRange getFlashRange() { + return dfu.getFlashRange(); + } + + @Override + public int getTransferSize() { + return dfu.getTransferSize(); + } + + @Override + public int receiveData(DfuCommmand dfuCommmand, short wValue, ByteBuffer byteBuffer) { + return transfer(dfu.getConnection(), USB_DIR_IN, dfuCommmand.getValue(), wValue, byteBuffer); + } + + @Override + public int sendData(DfuCommmand dfuCommmand, short wValue, ByteBuffer byteBuffer) { + return transfer(dfu.getConnection(), USB_DIR_OUT, dfuCommmand.getValue(), wValue, byteBuffer); + } + }; + + + DfuLogic.Logger logger = DfuLogic.Logger.CONSOLE; + try { +// DfuCommandGetStatus.State state = DfuCommandGetStatus.read(c); +// mResultView.append("State " + state + "\n"); + + DfuCommandGetStatus.DeviceStatus state = DfuCommandGetStatus.read(logger, c); + + if (state.getState() == DfuCommandGetStatus.State.APP_IDLE) { + System.out.println("Wow?"); + + + c.sendData(DfuCommmand.DETACH, (short) DFU_DETACH_TIMEOUT, ByteBuffer.allocateDirect(0)); + + + } + + if (state.getState() == DfuCommandGetStatus.State.APP_IDLE) { + System.out.println("Wow?2"); + + + c.sendData(DfuCommmand.DETACH, (short) DFU_DETACH_TIMEOUT, ByteBuffer.allocateDirect(0)); + + + } + + + DfuLogic.uploadImage(logger, c, dfuImage, dfu.getFlashRange()); + + } catch (IllegalStateException e) { + mResultView.append("Error " + e + "\n"); + } + } + + private static int transfer(UsbDeviceConnection connection, int direction, int request, short wValue, ByteBuffer byteBuffer) { + return connection.controlTransfer(REQUEST_TYPE_CLASS | RECIPIENT_INTERFACE | direction, request, + wValue, 0, byteBuffer.array(), byteBuffer.limit(), 500); } /**