diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java index f0ca1395..eaafd3eb 100644 --- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java @@ -32,49 +32,50 @@ public AndroidDeviceResetter(@NonNull final Context context, @NonNull final Blue _transport = new McuMgrBleTransport(context, bluetoothDevice); } - public void beginReset() + public EAndroidDeviceResetterInitializationVerdict beginReset() { - try - { - _manager = new DefaultManager(_transport); - } - catch (final Exception ex) - { - setState(EAndroidDeviceResetterState.FAILED); - onError("Failed to create manager: '" + ex.getMessage() + "'", ex); - return; - } + if (!IsCold()) + { //keep first + onError("[ADR.BR.000] Another reset operation is already in progress (state='" + _currentState + "')"); - setState(EAndroidDeviceResetterState.RESETTING); - - AndroidDeviceResetter self = this; + return EAndroidDeviceResetterInitializationVerdict.FAILED__OTHER_RESET_ALREADY_IN_PROGRESS; + } - _manager.reset(new McuMgrCallback() + try { + setState(EAndroidDeviceResetterState.IDLE); //order + _manager = new DefaultManager(_transport); //order + setState(EAndroidDeviceResetterState.RESETTING); //order - @Override - public void onResponse(@NotNull final McuMgrOsResponse response) + AndroidDeviceResetter self = this; + _manager.reset(new McuMgrCallback() { - if (!response.isSuccess()) - { // check for an error return code - self.onError("Reset failed (error-code '" + response.getReturnCode().toString() + "')", response.getReturnCode(), response.getGroupReturnCode()); - - setState(EAndroidDeviceResetterState.FAILED); - return; + @Override + public void onResponse(@NotNull final McuMgrOsResponse response) + { + if (!response.isSuccess()) + { // check for an error return code + self.onError("[ADR.BR.002] Reset failed (error-code '" + response.getReturnCode().toString() + "')", response.getReturnCode(), response.getGroupReturnCode()); + return; + } + + setState(EAndroidDeviceResetterState.COMPLETE); } - setState(EAndroidDeviceResetterState.COMPLETE); - } - - @Override - public void onError(@NotNull final McuMgrException exception) - { - self.onError("Reset failed '" + exception.getMessage() + "'", exception); - - setState(EAndroidDeviceResetterState.FAILED); - } + @Override + public void onError(@NotNull final McuMgrException exception) + { + self.onError("[ADR.BR.005] Reset failed '" + exception.getMessage() + "'", exception); + } + }); + } + catch (final Exception ex) + { + onError("[ADR.BR.010] Failed to initialize reset operation: '" + ex.getMessage() + "'", ex); + return EAndroidDeviceResetterInitializationVerdict.FAILED__ERROR_UPON_COMMENCING; + } - }); + return EAndroidDeviceResetterInitializationVerdict.SUCCESS; } public void disconnect() @@ -96,6 +97,13 @@ public EAndroidDeviceResetterState getState() private EAndroidDeviceResetterState _currentState = EAndroidDeviceResetterState.NONE; + @Contract(pure = true) + private boolean IsCold() + { + return _currentState == EAndroidDeviceResetterState.NONE + || _currentState == EAndroidDeviceResetterState.COMPLETE; + } + private void setState(final EAndroidDeviceResetterState newState) { final EAndroidDeviceResetterState oldState = _currentState; //order @@ -118,6 +126,11 @@ public String getLastFatalErrorMessage() return _lastFatalErrorMessage; } + private void onError(final String errorMessage) + { + onError(errorMessage, null); + } + private void onError(final String errorMessage, final Exception exception) { onErrorImpl(errorMessage, McuMgrExceptionHelpers.DeduceGlobalErrorCodeFromException(exception)); diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java index cadd1ade..2ac48c31 100644 --- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java @@ -147,23 +147,24 @@ public EAndroidFileDownloaderVerdict beginDownload( return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS; } - resetDownloadState(); //order must be called before ensureTransportIsInitializedExactlyOnce() because the environment might try to set the device via trySetBluetoothDevice()!!! - ensureTransportIsInitializedExactlyOnce(initialMtuSize); //order + try + { + resetDownloadState(); //order must be called before ensureTransportIsInitializedExactlyOnce() because the environment might try to set the device via trySetBluetoothDevice()!!! + ensureTransportIsInitializedExactlyOnce(initialMtuSize); //order + setLoggingEnabledOnConnection(false); //order - final EAndroidFileDownloaderVerdict verdict = ensureFilesystemManagerIsInitializedExactlyOnce(); //order - if (verdict != EAndroidFileDownloaderVerdict.SUCCESS) - return verdict; + final EAndroidFileDownloaderVerdict verdict = ensureFilesystemManagerIsInitializedExactlyOnce(); //order + if (verdict != EAndroidFileDownloaderVerdict.SUCCESS) + return verdict; - ensureFileDownloaderCallbackProxyIsInitializedExactlyOnce(); //order + tryEnsureConnectionPriorityOnTransport(); //order + ensureFileDownloaderCallbackProxyIsInitializedExactlyOnce(); //order - setLoggingEnabled(false); - try - { _downloadingController = _fileSystemManager.fileDownload(_remoteFilePathSanitized, _fileDownloaderCallbackProxy); } catch (final Exception ex) { - onError("[AFD.BD.060] Failed to initialize download: " + ex.getMessage(), ex); + onError("[AFD.BD.060] Failed to initialize the download operation: " + ex.getMessage(), ex); return EAndroidFileDownloaderVerdict.FAILED__ERROR_UPON_COMMENCING; } @@ -178,7 +179,7 @@ public void pause() return; setState(EAndroidFileDownloaderState.PAUSED); - setLoggingEnabled(true); + setLoggingEnabledOnConnection(true); transferController.pause(); busyStateChangedAdvertisement(false); } @@ -194,7 +195,7 @@ public void resume() busyStateChangedAdvertisement(true); _initialBytes = 0; - setLoggingEnabled(false); + setLoggingEnabledOnConnection(false); transferController.resume(); } @@ -233,10 +234,11 @@ private void resetDownloadState() private void ensureTransportIsInitializedExactlyOnce(int initialMtuSize) { - if (_transport != null) - return; + if (_transport == null) + { + _transport = new McuMgrBleTransport(_context, _bluetoothDevice); + } - _transport = new McuMgrBleTransport(_context, _bluetoothDevice); if (initialMtuSize > 0) { _transport.setInitialMtu(initialMtuSize); @@ -259,27 +261,20 @@ private EAndroidFileDownloaderVerdict ensureFilesystemManagerIsInitializedExactl try { _fileSystemManager = new FsManager(_transport); //order - - requestHighConnectionPriority(_fileSystemManager); //order } catch (final Exception ex) { onError("[AFD.EFMIIEO.010] Failed to initialize the filesystem manager: " + ex.getMessage(), ex); - return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS; + return EAndroidFileDownloaderVerdict.FAILED__ERROR_UPON_COMMENCING; } return EAndroidFileDownloaderVerdict.SUCCESS; } - private void requestHighConnectionPriority(FsManager fileSystemManager) + private void tryEnsureConnectionPriorityOnTransport() { - final McuMgrTransport mcuMgrTransporter = fileSystemManager.getTransporter(); - if (!(mcuMgrTransporter instanceof McuMgrBleTransport)) - return; - - final McuMgrBleTransport bleTransporter = (McuMgrBleTransport) mcuMgrTransporter; - bleTransporter.requestConnPriority(ConnectionPriorityRequest.CONNECTION_PRIORITY_HIGH); + _transport.requestConnPriority(ConnectionPriorityRequest.CONNECTION_PRIORITY_HIGH); } private void disposeTransport() @@ -321,13 +316,9 @@ private void disposeCallbackProxy() _fileDownloaderCallbackProxy = null; } - private void setLoggingEnabled(final boolean enabled) + private void setLoggingEnabledOnConnection(final boolean enabled) { - final McuMgrTransport mcuMgrTransporter = _fileSystemManager.getTransporter(); - if (!(mcuMgrTransporter instanceof McuMgrBleTransport)) - return; - - ((McuMgrBleTransport) mcuMgrTransporter).setLoggingEnabled(enabled); + _transport.setLoggingEnabled(enabled); } private void setState(final EAndroidFileDownloaderState newState) @@ -488,7 +479,7 @@ public void onDownloadFailed(@NonNull final McuMgrException exception) { fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0); onError(exception.getMessage(), exception); - setLoggingEnabled(true); + setLoggingEnabledOnConnection(true); busyStateChangedAdvertisement(false); _downloadingController = null; //game over @@ -500,7 +491,7 @@ public void onDownloadCanceled() fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0); setState(EAndroidFileDownloaderState.CANCELLED); cancelledAdvertisement(); - setLoggingEnabled(true); + setLoggingEnabledOnConnection(true); busyStateChangedAdvertisement(false); _downloadingController = null; //game over @@ -514,7 +505,7 @@ public void onDownloadCompleted(byte @NotNull [] data) setState(EAndroidFileDownloaderState.COMPLETE); // order vital downloadCompletedAdvertisement(_remoteFilePathSanitized, data); // order vital - setLoggingEnabled(true); + setLoggingEnabledOnConnection(true); busyStateChangedAdvertisement(false); _downloadingController = null; //game over diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java index 01c330d1..f7ce92cf 100644 --- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java @@ -157,19 +157,19 @@ public EAndroidFileUploaderVerdict beginUpload( return EAndroidFileUploaderVerdict.FAILED__INVALID_DATA; } - resetUploadState(); //order must be called before ensureTransportIsInitializedExactlyOnce() because the environment might try to set the device via trySetBluetoothDevice()!!! - ensureTransportIsInitializedExactlyOnce(initialMtuSize); //order - - final EAndroidFileUploaderVerdict verdict = ensureFilesystemManagerIsInitializedExactlyOnce(); //order - if (verdict != EAndroidFileUploaderVerdict.SUCCESS) - return verdict; + try + { + resetUploadState(); //order must be called before ensureTransportIsInitializedExactlyOnce() because the environment might try to set the device via trySetBluetoothDevice()!!! + ensureTransportIsInitializedExactlyOnce(initialMtuSize); //order + setLoggingEnabledOnTransport(false); //order - ensureFileUploaderCallbackProxyIsInitializedExactlyOnce(); //order + final EAndroidFileUploaderVerdict verdict = ensureFilesystemManagerIsInitializedExactlyOnce(); //order + if (verdict != EAndroidFileUploaderVerdict.SUCCESS) + return verdict; - setLoggingEnabled(false); + requestHighConnectionPriorityOnTransport(); //order + ensureFileUploaderCallbackProxyIsInitializedExactlyOnce(); //order - try - { FileUploader fileUploader = new FileUploader( //00 _fileSystemManager, _remoteFilePathSanitized, @@ -205,12 +205,10 @@ private void resetUploadState() private void ensureTransportIsInitializedExactlyOnce(int initialMtuSize) { - if (_transport != null) - return; - - logMessageAdvertisement("[AFU.ETIIEO.010] (Re)Initializing transport: initial-mtu-size=" + initialMtuSize, "FileUploader", "TRACE", _remoteFilePathSanitized); - - _transport = new McuMgrBleTransport(_context, _bluetoothDevice); + if (_transport == null) + { + _transport = new McuMgrBleTransport(_context, _bluetoothDevice); + } if (initialMtuSize > 0) { @@ -236,8 +234,6 @@ private EAndroidFileUploaderVerdict ensureFilesystemManagerIsInitializedExactlyO try { _fileSystemManager = new FsManager(_transport); //order - - requestHighConnectionPriority(_fileSystemManager); //order } catch (final Exception ex) { @@ -256,7 +252,7 @@ public void pause() return; setState(EAndroidFileUploaderState.PAUSED); - setLoggingEnabled(true); + setLoggingEnabledOnTransport(true); transferController.pause(); busyStateChangedAdvertisement(false); } @@ -272,7 +268,7 @@ public void resume() busyStateChangedAdvertisement(true); _initialBytes = 0; - setLoggingEnabled(false); + setLoggingEnabledOnTransport(false); transferController.resume(); } @@ -303,14 +299,9 @@ public void cancel(final String reason) transferController.cancel(); //order } - static private void requestHighConnectionPriority(final FsManager fileSystemManager) + private void requestHighConnectionPriorityOnTransport() { - final McuMgrTransport mcuMgrTransporter = fileSystemManager.getTransporter(); - if (!(mcuMgrTransporter instanceof McuMgrBleTransport)) - return; - - final McuMgrBleTransport bleTransporter = (McuMgrBleTransport) mcuMgrTransporter; - bleTransporter.requestConnPriority(ConnectionPriorityRequest.CONNECTION_PRIORITY_HIGH); + _transport.requestConnPriority(ConnectionPriorityRequest.CONNECTION_PRIORITY_HIGH); } private void disposeTransport() @@ -352,13 +343,9 @@ private void disposeCallbackProxy() _fileUploaderCallbackProxy = null; } - private void setLoggingEnabled(final boolean enabled) + private void setLoggingEnabledOnTransport(final boolean enabled) { - final McuMgrTransport mcuMgrTransporter = _fileSystemManager.getTransporter(); - if (!(mcuMgrTransporter instanceof McuMgrBleTransport)) - return; - - ((McuMgrBleTransport) mcuMgrTransporter).setLoggingEnabled(enabled); + _transport.setLoggingEnabled(enabled); } private void setState(final EAndroidFileUploaderState newState) @@ -503,7 +490,7 @@ public void onUploadFailed(@NonNull final McuMgrException error) { fileUploadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0); onError(error.getMessage(), error); - setLoggingEnabled(true); + setLoggingEnabledOnTransport(true); busyStateChangedAdvertisement(false); _uploadController = null; //order @@ -515,7 +502,7 @@ public void onUploadCanceled() fileUploadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0); setState(EAndroidFileUploaderState.CANCELLED); cancelledAdvertisement(_cancellationReason); - setLoggingEnabled(true); + setLoggingEnabledOnTransport(true); busyStateChangedAdvertisement(false); _uploadController = null; //order @@ -527,7 +514,7 @@ public void onUploadCompleted() //fileUploadProgressPercentageAndDataThroughputChangedAdvertisement(100, 0); //no need this is taken care of inside setState() setState(EAndroidFileUploaderState.COMPLETE); fileUploadedAdvertisement(_remoteFilePathSanitized); - setLoggingEnabled(true); + setLoggingEnabledOnTransport(true); busyStateChangedAdvertisement(false); _uploadController = null; //order diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java index 6ff5b9d3..4661c27a 100644 --- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java @@ -32,38 +32,54 @@ public AndroidFirmwareEraser(@NonNull final Context context, @NonNull final Blue _transport = new McuMgrBleTransport(context, bluetoothDevice); } - public void beginErasure(final int imageIndex) + public EAndroidFirmwareEraserInitializationVerdict beginErasure(final int imageIndex) { - busyStateChangedAdvertisement(true); - - setState(EAndroidFirmwareEraserState.ERASING); + if (!IsCold()) + { //keep first + onError("[AFE.BE.000] Another reset operation is already in progress (state='" + _currentState + "')"); - AndroidFirmwareEraser self = this; + return EAndroidFirmwareEraserInitializationVerdict.FAILED__OTHER_ERASURE_ALREADY_IN_PROGRESS; + } - _imageManager = new ImageManager(_transport); - _imageManager.erase(imageIndex, new McuMgrCallback() + try { - @Override - public void onResponse(@NonNull final McuMgrImageResponse response) + setState(EAndroidFirmwareEraserState.IDLE); //order + _imageManager = new ImageManager(_transport); //order + busyStateChangedAdvertisement(true); //order + setState(EAndroidFirmwareEraserState.ERASING); //order + + AndroidFirmwareEraser self = this; + _imageManager.erase(imageIndex, new McuMgrCallback() { - if (!response.isSuccess()) - { // check for an error return code - self.onError("[AFE.BE.OR.010] Erasure failed (error-code '" + response.getReturnCode().toString() + "')", response.getReturnCode(), response.getGroupReturnCode()); - return; + @Override + public void onResponse(@NonNull final McuMgrImageResponse response) + { + if (!response.isSuccess()) + { // check for an error return code + self.onError("[AFE.BE.010] Erasure failed (error-code '" + response.getReturnCode().toString() + "')", response.getReturnCode(), response.getGroupReturnCode()); + return; + } + + readImageErasure(); + setState(EAndroidFirmwareEraserState.COMPLETE); } - readImageErasure(); - setState(EAndroidFirmwareEraserState.COMPLETE); - } + @Override + public void onError(@NonNull final McuMgrException exception) + { + self.onError("[AFE.BE.020] Erasure failed '" + exception.getMessage() + "'", exception); - @Override - public void onError(@NonNull final McuMgrException exception) - { - self.onError("[AFE.BE.OE.010] Erasure failed '" + exception.getMessage() + "'", exception); + busyStateChangedAdvertisement(false); + } + }); + } + catch (final Exception ex) + { + onError("[AFE.BE.010] Failed to initialize erase operation: '" + ex.getMessage() + "'", ex); + return EAndroidFirmwareEraserInitializationVerdict.FAILED__ERROR_UPON_COMMENCING; + } - busyStateChangedAdvertisement(false); - } - }); + return EAndroidFirmwareEraserInitializationVerdict.SUCCESS; } public void disconnect() @@ -78,6 +94,13 @@ public void disconnect() mcuMgrTransporter.release(); } + @Contract(pure = true) + private boolean IsCold() + { + return _currentState == EAndroidFirmwareEraserState.NONE + || _currentState == EAndroidFirmwareEraserState.COMPLETE; + } + private EAndroidFirmwareEraserState _currentState = EAndroidFirmwareEraserState.NONE; private void setState(EAndroidFirmwareEraserState newState) @@ -103,6 +126,11 @@ public String getLastFatalErrorMessage() return _lastFatalErrorMessage; } + private void onError(final String errorMessage) + { + onError(errorMessage, null); + } + private void onError(final String errorMessage, final Exception exception) { onErrorImpl(errorMessage, McuMgrExceptionHelpers.DeduceGlobalErrorCodeFromException(exception)); diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java index 01f7c921..a9199f4a 100644 --- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java @@ -80,24 +80,9 @@ public EAndroidFirmwareInstallationVerdict beginInstallation( && _currentState != EAndroidFirmwareInstallationState.COMPLETE && _currentState != EAndroidFirmwareInstallationState.CANCELLED) { - return EAndroidFirmwareInstallationVerdict.FAILED__INSTALLATION_ALREADY_IN_PROGRESS; - } - - _manager = new FirmwareUpgradeManager(_transport); - _manager.setFirmwareUpgradeCallback(new FirmwareInstallCallbackProxy()); - - _handlerThread = new HandlerThread("AndroidFirmwareInstaller.HandlerThread"); //todo peer review whether this is the best way to go maybe we should be getting this from the call environment? - _handlerThread.start(); - - _handler = new Handler(_handlerThread.getLooper()); + onError(EAndroidFirmwareInstallerFatalErrorType.FAILED__INSTALLATION_ALREADY_IN_PROGRESS, "[AFI.BI.000] Another firmware installation is already in progress"); - if (estimatedSwapTimeInMilliseconds >= 0 && estimatedSwapTimeInMilliseconds <= 1000) - { //it is better to just warn the calling environment instead of erroring out - logMessageAdvertisement( - "Estimated swap-time of '" + estimatedSwapTimeInMilliseconds + "' milliseconds seems suspiciously low - did you mean to say '" + (estimatedSwapTimeInMilliseconds * 1000) + "' milliseconds?", - "FirmwareInstaller", - "WARN" - ); + return EAndroidFirmwareInstallationVerdict.FAILED__INSTALLATION_ALREADY_IN_PROGRESS; } ImageSet images = new ImageSet(); @@ -119,6 +104,23 @@ public EAndroidFirmwareInstallationVerdict beginInstallation( } } + _manager = new FirmwareUpgradeManager(_transport); + _manager.setFirmwareUpgradeCallback(new FirmwareInstallCallbackProxy()); + + _handlerThread = new HandlerThread("AndroidFirmwareInstaller.HandlerThread"); //todo peer review whether this is the best way to go maybe we should be getting this from the call environment? + _handlerThread.start(); + + _handler = new Handler(_handlerThread.getLooper()); + + if (estimatedSwapTimeInMilliseconds >= 0 && estimatedSwapTimeInMilliseconds <= 1000) + { //it is better to just warn the calling environment instead of erroring out + logMessageAdvertisement( + "Estimated swap-time of '" + estimatedSwapTimeInMilliseconds + "' milliseconds seems suspiciously low - did you mean to say '" + (estimatedSwapTimeInMilliseconds * 1000) + "' milliseconds?", + "FirmwareInstaller", + "WARN" + ); + } + @NotNull Settings settings; try { @@ -244,7 +246,12 @@ public String getLastFatalErrorMessage() return _lastFatalErrorMessage; } - public void onError(EAndroidFirmwareInstallerFatalErrorType fatalErrorType, final String errorMessage, Exception ex) + public void onError(final EAndroidFirmwareInstallerFatalErrorType fatalErrorType, final String errorMessage) + { + onError(fatalErrorType, errorMessage, null); + } + + public void onError(final EAndroidFirmwareInstallerFatalErrorType fatalErrorType, final String errorMessage, final Exception ex) { EAndroidFirmwareInstallationState currentStateSnapshot = _currentState; //00 order setState(EAndroidFirmwareInstallationState.ERROR); // order diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidDeviceResetterInitializationVerdict.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidDeviceResetterInitializationVerdict.java new file mode 100644 index 00000000..fdf6a23e --- /dev/null +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidDeviceResetterInitializationVerdict.java @@ -0,0 +1,17 @@ +package no.laerdal.mcumgr_laerdal_wrapper; + +public enum EAndroidDeviceResetterInitializationVerdict +{ + SUCCESS(0), + FAILED__ERROR_UPON_COMMENCING(1), //connection problems + FAILED__OTHER_RESET_ALREADY_IN_PROGRESS(2); + + @SuppressWarnings({"FieldCanBeLocal", "unused"}) + private final int _value; + + EAndroidDeviceResetterInitializationVerdict(int value) + { + _value = value; + } +} + diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFileUploaderVerdict.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFileUploaderVerdict.java index d90c590a..674e4bc5 100644 --- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFileUploaderVerdict.java +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFileUploaderVerdict.java @@ -16,3 +16,4 @@ public enum EAndroidFileUploaderVerdict //this must mirror the enum values of E[ _value = value; } } + diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFirmwareEraserInitializationVerdict.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFirmwareEraserInitializationVerdict.java new file mode 100644 index 00000000..e155a166 --- /dev/null +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFirmwareEraserInitializationVerdict.java @@ -0,0 +1,16 @@ +package no.laerdal.mcumgr_laerdal_wrapper; + +public enum EAndroidFirmwareEraserInitializationVerdict +{ + SUCCESS(0), + FAILED__ERROR_UPON_COMMENCING(1), //connection problems + FAILED__OTHER_ERASURE_ALREADY_IN_PROGRESS(2); + + @SuppressWarnings({"FieldCanBeLocal", "unused"}) + private final int _value; + + EAndroidFirmwareEraserInitializationVerdict(int value) + { + _value = value; + } +} diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFirmwareInstallerFatalErrorType.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFirmwareInstallerFatalErrorType.java index e7216131..580bca21 100644 --- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFirmwareInstallerFatalErrorType.java +++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/EAndroidFirmwareInstallerFatalErrorType.java @@ -7,7 +7,8 @@ public enum EAndroidFirmwareInstallerFatalErrorType //this must mirror the enum INVALID_FIRMWARE(2), DEPLOYMENT_FAILED(3), FIRMWARE_IMAGE_SWAP_TIMEOUT(4), - FIRMWARE_UPLOADING_ERRORED_OUT(5); + FIRMWARE_UPLOADING_ERRORED_OUT(5), + FAILED__INSTALLATION_ALREADY_IN_PROGRESS(6); @SuppressWarnings({"FieldCanBeLocal", "unused"}) private final int _value; diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS.xcodeproj/project.pbxproj b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS.xcodeproj/project.pbxproj index 6e3607a6..63a1048c 100644 --- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS.xcodeproj/project.pbxproj +++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ B028FB802940DF1400CB71EB /* iOSMcuManagerLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = B028FB7F2940DF1400CB71EB /* iOSMcuManagerLibrary */; }; + B04DC3652CD3C7810048B553 /* EIOSDeviceResetInitializationVerdict.swift in Sources */ = {isa = PBXBuildFile; fileRef = B04DC3642CD3C7810048B553 /* EIOSDeviceResetInitializationVerdict.swift */; }; + B04DC3672CD3E1A20048B553 /* EIOSFirmwareErasureInitializationVerdict.swift in Sources */ = {isa = PBXBuildFile; fileRef = B04DC3662CD3E1A20048B553 /* EIOSFirmwareErasureInitializationVerdict.swift */; }; B0FF8AE92CCFF8E1004B39DE /* IOSListenerForFileUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0FF8AE82CCFF8E1004B39DE /* IOSListenerForFileUploader.swift */; }; E769D0FFF3A39C575B982F6D /* InvalidFirmwareInstallationModeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E769DB7090742CC7D6AFD01D /* InvalidFirmwareInstallationModeError.swift */; }; E769D1175ADD137DCA6B0207 /* EIOSFirmwareEraserState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E769D3130BA737A0C282D1DD /* EIOSFirmwareEraserState.swift */; }; @@ -36,6 +38,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + B04DC3642CD3C7810048B553 /* EIOSDeviceResetInitializationVerdict.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIOSDeviceResetInitializationVerdict.swift; sourceTree = ""; }; + B04DC3662CD3E1A20048B553 /* EIOSFirmwareErasureInitializationVerdict.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EIOSFirmwareErasureInitializationVerdict.swift; sourceTree = ""; }; B0C562262936567900B070BA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; B0C562282936568800B070BA /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk/System/Library/Frameworks/CoreBluetooth.framework; sourceTree = DEVELOPER_DIR; }; B0FF8AE82CCFF8E1004B39DE /* IOSListenerForFileUploader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOSListenerForFileUploader.swift; sourceTree = ""; }; @@ -100,6 +104,8 @@ E769DC768A6D6F0D1CAC3C06 /* McuMgrBindingsiOS.h */, E769D3E2D33EE281518619A7 /* IOSFirmwareInstaller.swift */, E769D1DEDAD5F89C361DF28C /* EIOSFirmwareInstallationVerdict.swift */, + B04DC3642CD3C7810048B553 /* EIOSDeviceResetInitializationVerdict.swift */, + B04DC3662CD3E1A20048B553 /* EIOSFirmwareErasureInitializationVerdict.swift */, E769DC8A37490B096716C6B8 /* EIOSFirmwareInstallationMode.swift */, E769DCEDC8442691AF65E8F8 /* EIOSFirmwareInstallationState.swift */, E769DB7090742CC7D6AFD01D /* InvalidFirmwareInstallationModeError.swift */, @@ -237,6 +243,7 @@ E769D37F2EF53CC9C5858BED /* IOSListenerForFirmwareInstaller.swift in Sources */, E769D36EAF2DD40E0A892DB2 /* DummyPlaceholder.swift in Sources */, E769D8E49B6F52BD0065A849 /* EIOSFileUploaderState.swift in Sources */, + B04DC3652CD3C7810048B553 /* EIOSDeviceResetInitializationVerdict.swift in Sources */, E769DA011D5897CB39E02602 /* IOSFileUploader.swift in Sources */, E769DEB3EFF58D41D88197C4 /* EIOSFileUploadingInitializationVerdict.swift in Sources */, E769D339FCECEE79EEDD55C5 /* McuMgrExceptionHelpers.swift in Sources */, @@ -244,6 +251,7 @@ B0FF8AE92CCFF8E1004B39DE /* IOSListenerForFileUploader.swift in Sources */, E769D33171D78172F096C8A4 /* EIOSFileDownloaderState.swift in Sources */, E769D3F56B12BF1FA2695F1E /* IOSListenerForFileDownloader.swift in Sources */, + B04DC3672CD3E1A20048B553 /* EIOSFirmwareErasureInitializationVerdict.swift in Sources */, E769D54A54C788CCE8488B9B /* EIOSFileDownloadingInitializationVerdict.swift in Sources */, E769D5AE4CFECFEA0B509626 /* EIOSFirmwareInstallationFatalError.swift in Sources */, ); diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSDeviceResetInitializationVerdict.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSDeviceResetInitializationVerdict.swift new file mode 100644 index 00000000..41f50caa --- /dev/null +++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSDeviceResetInitializationVerdict.swift @@ -0,0 +1,6 @@ +@objc +public enum EIOSDeviceResetInitializationVerdict: Int { + case success = 0 + case failedErrorUponCommencing = 1 + case failedOtherResetAlreadyInProgress = 2 +} diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSFirmwareErasureInitializationVerdict.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSFirmwareErasureInitializationVerdict.swift new file mode 100644 index 00000000..d88d44c8 --- /dev/null +++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSFirmwareErasureInitializationVerdict.swift @@ -0,0 +1,6 @@ +@objc +public enum EIOSFirmwareErasureInitializationVerdict: Int { + case success = 0 + case failedErrorUponCommencing = 1 + case failedOtherErasureAlreadyInProgress = 2 +} diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSFirmwareInstallationFatalError.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSFirmwareInstallationFatalError.swift index b84c3cc4..ef49787d 100644 --- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSFirmwareInstallationFatalError.swift +++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/EIOSFirmwareInstallationFatalError.swift @@ -7,4 +7,5 @@ public enum EIOSFirmwareInstallerFatalErrorType : Int //this must mirror the enu case deploymentFailed = 3 case firmwareImageSwapTimeout = 4 case firmwareUploadingErroredOut = 5 + case failedInstallationAlreadyInProgress = 6 } diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSDeviceResetter.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSDeviceResetter.swift index d63271b7..6a1d4b3a 100644 --- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSDeviceResetter.swift +++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSDeviceResetter.swift @@ -17,30 +17,50 @@ public class IOSDeviceResetter: NSObject { } @objc - public func beginReset() { - setState(.resetting) + public func beginReset(_ keepThisDummyParameter: Bool = false) -> EIOSDeviceResetInitializationVerdict { + if (!isCold()) { //keep first + onError("[IOSDR.BR.000] Another erasure operation is already in progress") - _manager = DefaultManager(transport: _transporter) - _manager.logDelegate = self + return .failedOtherResetAlreadyInProgress + } - _manager.reset { - response, error in + do { + setState(.idle) + _manager = DefaultManager(transport: _transporter) + _manager.logDelegate = self - if (error != nil) { - self.onError("[IOSDR.BR.010] Reset failed: '\(error?.localizedDescription ?? "")'", error) - return - } + setState(.resetting) + _manager.reset { + response, error in + + if (error != nil) { + self.onError("[IOSDR.BR.010] Reset failed: '\(error?.localizedDescription ?? "")'", error) + return + } + + if (response?.getError() != nil) { // check for an error return code + self.onError("[IOSDR.BR.020] Reset failed: '\(response?.getError()?.errorDescription ?? "")'", response?.getError()) + return + } - if (response?.getError() != nil) { // check for an error return code - self.onError("[IOSDR.BR.020] Reset failed: '\(response?.getError()?.errorDescription ?? "")'", response?.getError()) - return + self.setState(.complete) } + } catch let ex { + onError("[IOSDR.BR.030] Failed to launch the installation process: '\(ex.localizedDescription)", ex) - self.setState(.complete) + return .failedErrorUponCommencing } + + return .success + } + + private func isCold() -> Bool { + return _currentState == .none + || _currentState == .failed + || _currentState == .complete } - private func onError(_ errorMessage: String, _ error: Error?) { + private func onError(_ errorMessage: String, _ error: Error? = nil) { setState(.failed) fatalErrorOccurredAdvertisement(errorMessage, McuMgrExceptionHelpers.deduceGlobalErrorCodeFromException(error)) diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareEraser.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareEraser.swift index 15209b17..dd2a4ed8 100644 --- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareEraser.swift +++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareEraser.swift @@ -17,25 +17,39 @@ public class IOSFirmwareEraser: NSObject { } @objc - public func beginErasure(_ imageIndex: Int) { - busyStateChangedAdvertisement(true) + public func beginErasure(_ imageIndex: Int) -> EIOSFirmwareErasureInitializationVerdict { + if (!isCold()) { //keep first + onError("[IOSFE.BE.000] Another erasure operation is already in progress"); - setState(.erasing) + return .failedOtherErasureAlreadyInProgress; + } - _manager = ImageManager(transport: _transporter) - _manager.logDelegate = self + do + { + setState(.idle) + _manager = ImageManager(transport: _transporter) + _manager.logDelegate = self - _manager.erase { - response, error in + setState(.erasing) + busyStateChangedAdvertisement(true) + _manager.erase { + response, error in - if (error != nil) { - self.onError("[IOSFE.BE.010] Failed to start firmware erasure: \(error?.localizedDescription ?? "An unspecified error occurred")", error) - return + if (error != nil) { + self.onError("[IOSFE.BE.010] Failed to start firmware erasure: \(error?.localizedDescription ?? "An unspecified error occurred")", error) + return + } + + self.readImageErasure() + self.setState(.complete) } + } catch let ex { + onError("[IOSFE.BE.020] Failed to launch the installation process: '\(ex.localizedDescription)", ex) - self.readImageErasure() - self.setState(.complete) + return .failedErrorUponCommencing } + + return .success } @objc @@ -43,10 +57,16 @@ public class IOSFirmwareEraser: NSObject { _transporter?.close() } - private func onError(_ errorMessage: String, _ error: Error?) { + private func isCold() -> Bool { + return _currentState == .none + || _currentState == .failed + || _currentState == .complete + } + + private func onError(_ errorMessage: String, _ error: Error? = nil) { setState(.failed) - fatalErrorOccurredAdvertisement(errorMessage, McuMgrExceptionHelpers.deduceGlobalErrorCodeFromException(error)) busyStateChangedAdvertisement(false) + fatalErrorOccurredAdvertisement(errorMessage, McuMgrExceptionHelpers.deduceGlobalErrorCodeFromException(error)) } private var _lastFatalErrorMessage: String @@ -117,4 +137,4 @@ extension IOSFirmwareEraser: McuMgrLogDelegate { level.name ) } -} \ No newline at end of file +} diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareInstaller.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareInstaller.swift index 1689f8f1..079f62e8 100644 --- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareInstaller.swift +++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFirmwareInstaller.swift @@ -30,7 +30,9 @@ public class IOSFirmwareInstaller: NSObject { _ pipelineDepth: Int, _ byteAlignment: Int ) -> EIOSFirmwareInstallationVerdict { - if _currentState != .none && _currentState != .cancelled && _currentState != .complete && _currentState != .error { //if another installation is already in progress we bail out + if !isCold() { //if another installation is already in progress we bail out + onError(.failedInstallationAlreadyInProgress, "[IOSFI.BI.000] Another firmware installation is already in progress") + return .failedInstallationAlreadyInProgress } @@ -38,20 +40,20 @@ public class IOSFirmwareInstaller: NSObject { _lastBytesSendTimestamp = nil if (imageData.isEmpty) { - emitFatalError(.invalidFirmware, "[IOSFI.BI.010] The firmware data-bytes given are dud!") + onError(.invalidFirmware, "[IOSFI.BI.010] The firmware data-bytes given are dud") return .failedInvalidFirmware } if (pipelineDepth >= 2 && byteAlignment <= 1) { - emitFatalError(.invalidSettings, "[IOSFI.BI.020] When pipeline-depth is set to 2 or above you must specify a byte-alignment >=2 (given byte-alignment is '\(byteAlignment)')") + onError(.invalidSettings, "[IOSFI.BI.020] When pipeline-depth is set to 2 or above you must specify a byte-alignment >=2 (given byte-alignment is '\(byteAlignment)')") return .failedInvalidSettings } let byteAlignmentEnum = translateByteAlignmentMode(byteAlignment); if (byteAlignmentEnum == nil) { - emitFatalError(.invalidSettings, "[IOSFI.BI.030] Invalid byte-alignment value '\(byteAlignment)': It must be a power of 2 up to 16") + onError(.invalidSettings, "[IOSFI.BI.030] Invalid byte-alignment value '\(byteAlignment)': It must be a power of 2 up to 16") return .failedInvalidSettings } @@ -84,7 +86,7 @@ public class IOSFirmwareInstaller: NSObject { } } catch let ex { - emitFatalError(.invalidSettings, "[IOSFI.BI.050] Failed to configure the firmware-installer: '\(ex.localizedDescription)") + onError(.invalidSettings, "[IOSFI.BI.050] Failed to configure the firmware-installer: '\(ex.localizedDescription)") return .failedInvalidSettings } @@ -105,7 +107,7 @@ public class IOSFirmwareInstaller: NSObject { ) } catch let ex { - emitFatalError(.deploymentFailed, "[IOSFI.BI.060] Failed to launch the installation process: '\(ex.localizedDescription)") + onError(.deploymentFailed, "[IOSFI.BI.060] Failed to launch the installation process: '\(ex.localizedDescription)") return .failedDeploymentError } @@ -118,6 +120,13 @@ public class IOSFirmwareInstaller: NSObject { // //2 the hashing algorithm is very specific to nordic there is no practical way to go about getting it other than using the McuMgrImage utility class } + + private func isCold() -> Bool { + return _currentState == .none + || _currentState == .error + || _currentState == .complete + || _currentState == .cancelled + } private func calculateHashBytesOfData(_ data: Data) -> Data { var hasher = Hasher() @@ -183,7 +192,7 @@ public class IOSFirmwareInstaller: NSObject { _transporter?.close() } - private func emitFatalError(_ fatalErrorType: EIOSFirmwareInstallerFatalErrorType, _ errorMessage: String, _ error: Error? = nil) { + private func onError(_ fatalErrorType: EIOSFirmwareInstallerFatalErrorType, _ errorMessage: String, _ error: Error? = nil) { let currentStateSnapshot = _currentState //00 order setState(.error) // order fatalErrorOccurredAdvertisement( // order @@ -315,7 +324,7 @@ extension IOSFirmwareInstaller: FirmwareUpgradeDelegate { //todo calculate thr fatalErrorType = .firmwareImageSwapTimeout } - emitFatalError(fatalErrorType, error.localizedDescription, error) + onError(fatalErrorType, error.localizedDescription, error) busyStateChangedAdvertisement(false) } diff --git a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldCompleteSuccessfully_GivenGreenNativeDeviceResetter.cs b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldCompleteSuccessfully_GivenGreenNativeDeviceResetter.cs index d7faf17b..6ccb5834 100644 --- a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldCompleteSuccessfully_GivenGreenNativeDeviceResetter.cs +++ b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldCompleteSuccessfully_GivenGreenNativeDeviceResetter.cs @@ -37,7 +37,7 @@ public MockedGreenNativeDeviceResetterProxySpy1(INativeDeviceResetterCallbacksPr { } - public override void BeginReset() + public override EDeviceResetterInitializationVerdict BeginReset() { base.BeginReset(); @@ -49,6 +49,8 @@ public override void BeginReset() await Task.Delay(20); StateChangedAdvertisement(oldState: EDeviceResetterState.Resetting, newState: EDeviceResetterState.Complete); }); + + return EDeviceResetterInitializationVerdict.Success; //00 simulating the state changes in a background thread is vital in order to simulate the async nature of the native resetter } diff --git a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterErroredOutException_GivenBluetoothErrorDuringReset.cs b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterErroredOutException_GivenBluetoothErrorDuringReset.cs index b5443d3e..d3bf3efd 100644 --- a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterErroredOutException_GivenBluetoothErrorDuringReset.cs +++ b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterErroredOutException_GivenBluetoothErrorDuringReset.cs @@ -49,7 +49,7 @@ public MockedErroneousDueToBluetoothNativeDeviceResetterProxySpy(INativeDeviceRe { } - public override void BeginReset() + public override EDeviceResetterInitializationVerdict BeginReset() { base.BeginReset(); @@ -64,6 +64,8 @@ public override void BeginReset() //00 simulating the state changes in a background thread is vital in order to simulate the async nature of the native resetter }); + + return EDeviceResetterInitializationVerdict.Success; } } } diff --git a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterInternalErrorException_GivenErroneousDueToMissingNativeSymbolsNativeDeviceResetterProxy.cs b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterInternalErrorException_GivenErroneousDueToMissingNativeSymbolsNativeDeviceResetterProxy.cs index ac26dd25..41bb8f18 100644 --- a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterInternalErrorException_GivenErroneousDueToMissingNativeSymbolsNativeDeviceResetterProxy.cs +++ b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowDeviceResetterInternalErrorException_GivenErroneousDueToMissingNativeSymbolsNativeDeviceResetterProxy.cs @@ -44,7 +44,7 @@ public MockedErroneousDueToMissingSymbolsNativeDeviceResetterProxySpy(INativeDev { } - public override void BeginReset() + public override EDeviceResetterInitializationVerdict BeginReset() { base.BeginReset(); diff --git a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs index 824b34a7..bb1e4bc5 100644 --- a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs +++ b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.ResetAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs @@ -48,7 +48,7 @@ public MockedGreenButSlowNativeDeviceResetterProxySpy(INativeDeviceResetterCallb { } - public override void BeginReset() + public override EDeviceResetterInitializationVerdict BeginReset() { base.BeginReset(); @@ -60,6 +60,8 @@ public override void BeginReset() await Task.Delay(1_000); StateChangedAdvertisement(oldState: EDeviceResetterState.Resetting, newState: EDeviceResetterState.Complete); }); + + return EDeviceResetterInitializationVerdict.Success; //00 simulating the state changes in a background thread is vital in order to simulate the async nature of the native resetter } diff --git a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.cs b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.cs index 8861ed5a..6483e3de 100644 --- a/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.cs +++ b/Laerdal.McuMgr.Tests/DeviceResetter/DeviceResetterTestbed.cs @@ -29,9 +29,11 @@ protected MockedNativeDeviceResetterProxySpy(INativeDeviceResetterCallbacksProxy _resetterCallbacksProxy = resetterCallbacksProxy; } - public virtual void BeginReset() + public virtual EDeviceResetterInitializationVerdict BeginReset() { BeginResetCalled = true; + + return EDeviceResetterInitializationVerdict.Success; } public virtual void Disconnect() diff --git a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldCompleteSuccessfully_GivenGreenNativeFirmwareEraser.cs b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldCompleteSuccessfully_GivenGreenNativeFirmwareEraser.cs index 246315f1..9af1a987 100644 --- a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldCompleteSuccessfully_GivenGreenNativeFirmwareEraser.cs +++ b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldCompleteSuccessfully_GivenGreenNativeFirmwareEraser.cs @@ -32,7 +32,7 @@ public MockedGreenNativeFirmwareEraserProxySpy1(INativeFirmwareEraserCallbacksPr { } - public override void BeginErasure(int imageIndex) + public override EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex) { base.BeginErasure(imageIndex); @@ -44,6 +44,8 @@ public override void BeginErasure(int imageIndex) await Task.Delay(20); StateChangedAdvertisement(EFirmwareErasureState.Erasing, EFirmwareErasureState.Complete); }); + + return EFirmwareErasureInitializationVerdict.Success; //00 simulating the state changes in a background thread is vital in order to simulate the async nature of the native eraser } diff --git a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowFirmwareErasureInternalErrorException_GivenErroneousNativeFirmwareEraser.cs b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowFirmwareErasureInternalErrorException_GivenErroneousNativeFirmwareEraser.cs index 54bf08e5..e1bc0dbd 100644 --- a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowFirmwareErasureInternalErrorException_GivenErroneousNativeFirmwareEraser.cs +++ b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowFirmwareErasureInternalErrorException_GivenErroneousNativeFirmwareEraser.cs @@ -40,7 +40,7 @@ public MockedErroneousNativeFirmwareEraserProxySpy(INativeFirmwareEraserCallback { } - public override void BeginErasure(int imageIndex) + public override EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex) { base.BeginErasure(imageIndex); diff --git a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs index 68eb5d48..67277ff5 100644 --- a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs +++ b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.EraseAsync.ShouldThrowTimeoutException_GivenTooSmallTimeout.cs @@ -46,7 +46,7 @@ public MockedGreenButSlowNativeFirmwareEraserProxySpy(INativeFirmwareEraserCallb { } - public override void BeginErasure(int imageIndex) + public override EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex) { base.BeginErasure(imageIndex); @@ -58,6 +58,8 @@ public override void BeginErasure(int imageIndex) await Task.Delay(1_000); StateChangedAdvertisement(oldState: EFirmwareErasureState.Erasing, newState: EFirmwareErasureState.Complete); }); + + return EFirmwareErasureInitializationVerdict.Success; //00 simulating the state changes in a background thread is vital in order to simulate the async nature of the native resetter } diff --git a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.cs b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.cs index 5bf70aa4..9e20bece 100644 --- a/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.cs +++ b/Laerdal.McuMgr.Tests/FirmwareEraser/FirmwareEraserTestbed.cs @@ -27,9 +27,11 @@ protected MockedNativeFirmwareEraserProxySpy(INativeFirmwareEraserCallbacksProxy _eraserCallbacksProxy = eraserCallbacksProxy; } - public virtual void BeginErasure(int imageIndex) + public virtual EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex) { BeginErasureCalled = true; + + return EFirmwareErasureInitializationVerdict.Success; } public virtual void Disconnect() diff --git a/Laerdal.McuMgr/Droid/DeviceResetter/DeviceResetter.cs b/Laerdal.McuMgr/Droid/DeviceResetter/DeviceResetter.cs index f00c1ad2..d00f0c03 100644 --- a/Laerdal.McuMgr/Droid/DeviceResetter/DeviceResetter.cs +++ b/Laerdal.McuMgr/Droid/DeviceResetter/DeviceResetter.cs @@ -60,6 +60,11 @@ internal AndroidNativeDeviceResetterAdapterProxy(INativeDeviceResetterCallbacksP _deviceResetterCallbacksProxy = deviceResetterCallbacksProxy ?? throw new ArgumentNullException(nameof(deviceResetterCallbacksProxy)); } + public EDeviceResetterInitializationVerdict BeginReset() + { + return TranslateEAndroidDeviceResetterInitializationVerdict(base.BeginReset()); + } + public override void FatalErrorOccurredAdvertisement(string errorMessage, int globalErrorCode) { base.FatalErrorOccurredAdvertisement(errorMessage, globalErrorCode); @@ -137,6 +142,26 @@ static private EDeviceResetterState TranslateEAndroidDeviceResetterState(EAndroi throw new ArgumentOutOfRangeException(nameof(state), state, "Unknown enum value"); } + + static private EDeviceResetterInitializationVerdict TranslateEAndroidDeviceResetterInitializationVerdict(EAndroidDeviceResetterInitializationVerdict verdict) + { + if (verdict == EAndroidDeviceResetterInitializationVerdict.Success) + { + return EDeviceResetterInitializationVerdict.Success; + } + + if (verdict == EAndroidDeviceResetterInitializationVerdict.FailedErrorUponCommencing) + { + return EDeviceResetterInitializationVerdict.FailedErrorUponCommencing; + } + + if (verdict == EAndroidDeviceResetterInitializationVerdict.FailedOtherResetAlreadyInProgress) + { + return EDeviceResetterInitializationVerdict.FailedOtherResetAlreadyInProgress; + } + + throw new ArgumentOutOfRangeException(nameof(verdict), verdict, "Unknown enum value"); + } } } } diff --git a/Laerdal.McuMgr/Droid/FirmwareEraser/FirmwareEraser.cs b/Laerdal.McuMgr/Droid/FirmwareEraser/FirmwareEraser.cs index 2b23858f..9797b86b 100644 --- a/Laerdal.McuMgr/Droid/FirmwareEraser/FirmwareEraser.cs +++ b/Laerdal.McuMgr/Droid/FirmwareEraser/FirmwareEraser.cs @@ -66,6 +66,14 @@ public IFirmwareEraserEventEmittable FirmwareEraser //keep this to conform to th set => _nativeEraserCallbacksProxy!.FirmwareEraser = value; } + public EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex) + { + if (_nativeEraserCallbacksProxy == null) + throw new InvalidOperationException("The native firmware eraser is not initialized"); + + return TranslateEAndroidFirmwareEraserInitializationVerdict(base.BeginErasure(imageIndex)); + } + public override void StateChangedAdvertisement(EAndroidFirmwareEraserState oldState, EAndroidFirmwareEraserState newState) { base.StateChangedAdvertisement(oldState, newState); @@ -76,7 +84,7 @@ public override void StateChangedAdvertisement(EAndroidFirmwareEraserState oldSt ); } - //keep this override its needed to conform to the interface + //keep this override it is needed to conform to the interface public void StateChangedAdvertisement(EFirmwareErasureState oldState, EFirmwareErasureState newState) { _nativeEraserCallbacksProxy?.StateChangedAdvertisement(newState: newState, oldState: oldState); @@ -112,7 +120,7 @@ public override void LogMessageAdvertisement(string message, string category, st ); } - //keep this override its needed to conform to the interface + //keep this override it is needed to conform to the interface public void LogMessageAdvertisement(string message, string category, ELogLevel level) { _nativeEraserCallbacksProxy?.LogMessageAdvertisement(message, category, level); @@ -148,6 +156,26 @@ static internal EFirmwareErasureState TranslateEAndroidFirmwareEraserState(EAndr throw new ArgumentOutOfRangeException(nameof(state), state, "Unknown enum value"); } + + static internal EFirmwareErasureInitializationVerdict TranslateEAndroidFirmwareEraserInitializationVerdict(EAndroidFirmwareEraserInitializationVerdict beginErasure) + { + if (beginErasure == EAndroidFirmwareEraserInitializationVerdict.Success) + { + return EFirmwareErasureInitializationVerdict.Success; + } + + if (beginErasure == EAndroidFirmwareEraserInitializationVerdict.FailedErrorUponCommencing) + { + return EFirmwareErasureInitializationVerdict.FailedErrorUponCommencing; + } + + if (beginErasure == EAndroidFirmwareEraserInitializationVerdict.FailedOtherErasureAlreadyInProgress) + { + return EFirmwareErasureInitializationVerdict.FailedOtherErasureAlreadyInProgress; + } + + throw new ArgumentOutOfRangeException(nameof(beginErasure), beginErasure, "Unknown enum value"); + } } } } diff --git a/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs b/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs index 82967c15..4aa4d86b 100644 --- a/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs +++ b/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs @@ -296,6 +296,11 @@ static private EFirmwareInstallerFatalErrorType TranslateEAndroidFirmwareInstall return EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut; } + if (fatalErrorType == EAndroidFirmwareInstallerFatalErrorType.FailedInstallationAlreadyInProgress) + { + return EFirmwareInstallerFatalErrorType.FailedInstallationAlreadyInProgress; + } + throw new ArgumentOutOfRangeException(nameof(fatalErrorType), fatalErrorType, "Unknown enum value"); } diff --git a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Enums/EDeviceResetterInitializationVerdict.cs b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Enums/EDeviceResetterInitializationVerdict.cs new file mode 100644 index 00000000..4eca91d3 --- /dev/null +++ b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Enums/EDeviceResetterInitializationVerdict.cs @@ -0,0 +1,9 @@ +namespace Laerdal.McuMgr.DeviceResetter.Contracts.Enums +{ + public enum EDeviceResetterInitializationVerdict + { + Success = 0, + FailedErrorUponCommencing = 1, + FailedOtherResetAlreadyInProgress = 2, + } +} \ No newline at end of file diff --git a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Enums/EDeviceResetterState.cs b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Enums/EDeviceResetterState.cs index 846a6ebb..52d2165a 100644 --- a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Enums/EDeviceResetterState.cs +++ b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Enums/EDeviceResetterState.cs @@ -6,6 +6,6 @@ public enum EDeviceResetterState Idle = 1, Resetting = 2, Complete = 3, - Failed = 4 + Failed = 4, } } \ No newline at end of file diff --git a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/IDeviceResetterCommandable.cs b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/IDeviceResetterCommandable.cs index df4ee227..1509d665 100644 --- a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/IDeviceResetterCommandable.cs +++ b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/IDeviceResetterCommandable.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Laerdal.McuMgr.DeviceResetter.Contracts.Enums; namespace Laerdal.McuMgr.DeviceResetter.Contracts { @@ -11,7 +12,7 @@ public interface IDeviceResetterCommandable Task ResetAsync(int timeoutInMs = -1); /// Starts the resetting process. Basically reboots the device - it doesn't delete any of the firmware or the configuration. - void BeginReset(); + EDeviceResetterInitializationVerdict BeginReset(); /// Drops the active bluetooth-connection to the Zephyr device. void Disconnect(); diff --git a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterCommandableProxy.cs b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterCommandableProxy.cs index 3593da6a..a7b473b9 100644 --- a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterCommandableProxy.cs +++ b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterCommandableProxy.cs @@ -1,8 +1,10 @@ -namespace Laerdal.McuMgr.DeviceResetter.Contracts.Native +using Laerdal.McuMgr.DeviceResetter.Contracts.Enums; + +namespace Laerdal.McuMgr.DeviceResetter.Contracts.Native { internal interface INativeDeviceResetterCommandableProxy { void Disconnect(); - void BeginReset(); + EDeviceResetterInitializationVerdict BeginReset(); } } diff --git a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterProxy.cs b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterProxy.cs index d1af2921..ff3a5bc2 100644 --- a/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterProxy.cs +++ b/Laerdal.McuMgr/Shared/DeviceResetter/Contracts/Native/INativeDeviceResetterProxy.cs @@ -1,6 +1,9 @@ namespace Laerdal.McuMgr.DeviceResetter.Contracts.Native { - internal interface INativeDeviceResetterProxy : INativeDeviceResetterQueryableProxy, INativeDeviceResetterCommandableProxy, INativeDeviceResetterCallbacksProxy + internal interface INativeDeviceResetterProxy : + INativeDeviceResetterQueryableProxy, + INativeDeviceResetterCommandableProxy, + INativeDeviceResetterCallbacksProxy { } } diff --git a/Laerdal.McuMgr/Shared/DeviceResetter/DeviceResetter.cs b/Laerdal.McuMgr/Shared/DeviceResetter/DeviceResetter.cs index 50e67893..ff40e62f 100644 --- a/Laerdal.McuMgr/Shared/DeviceResetter/DeviceResetter.cs +++ b/Laerdal.McuMgr/Shared/DeviceResetter/DeviceResetter.cs @@ -54,7 +54,13 @@ internal DeviceResetter(INativeDeviceResetterProxy nativeDeviceResetterProxy) public string LastFatalErrorMessage => _nativeDeviceResetterProxy?.LastFatalErrorMessage; public void Disconnect() => _nativeDeviceResetterProxy?.Disconnect(); - public void BeginReset() => _nativeDeviceResetterProxy?.BeginReset(); + public EDeviceResetterInitializationVerdict BeginReset() + { + if (_nativeDeviceResetterProxy == null) + throw new InvalidOperationException("The native device resetter is not initialized"); + + return _nativeDeviceResetterProxy.BeginReset(); + } private event EventHandler _logEmitted; private event EventHandler _stateChanged; @@ -99,7 +105,9 @@ public async Task ResetAsync(int timeoutInMs = -1) StateChanged += DeviceResetter_StateChanged_; FatalErrorOccurred += DeviceResetter_FatalErrorOccurred_; - BeginReset(); //00 dont use task.run here for now + var verdict = BeginReset(); //00 dont use task.run here for now + if (verdict != EDeviceResetterInitializationVerdict.Success) + throw new ArgumentException(verdict.ToString()); _ = timeoutInMs <= 0 ? await taskCompletionSource.Task diff --git a/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/Enums/EFirmwareErasureInitializationVerdict.cs b/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/Enums/EFirmwareErasureInitializationVerdict.cs new file mode 100644 index 00000000..a12b6312 --- /dev/null +++ b/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/Enums/EFirmwareErasureInitializationVerdict.cs @@ -0,0 +1,9 @@ +namespace Laerdal.McuMgr.FirmwareEraser.Contracts.Enums +{ + public enum EFirmwareErasureInitializationVerdict + { + Success = 0, + FailedErrorUponCommencing = 1, + FailedOtherErasureAlreadyInProgress = 2, + } +} \ No newline at end of file diff --git a/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/IFirmwareEraserCommandable.cs b/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/IFirmwareEraserCommandable.cs index 59828196..db9965ee 100644 --- a/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/IFirmwareEraserCommandable.cs +++ b/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/IFirmwareEraserCommandable.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Laerdal.McuMgr.FirmwareEraser.Contracts.Enums; namespace Laerdal.McuMgr.FirmwareEraser.Contracts { @@ -18,7 +19,7 @@ public interface IFirmwareEraserCommandable /// Starts the erasure process on the firmware-image specified. /// /// The zero-based index of the firmware image to delete. By default it's 1 which is the index of the inactive firmware image. - void BeginErasure(int imageIndex = 1); + EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex = 1); /// Drops the active bluetooth-connection to the Zephyr device. void Disconnect(); diff --git a/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/Native/INativeFirmwareEraserCommandableProxy.cs b/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/Native/INativeFirmwareEraserCommandableProxy.cs index 61cceedb..418920f6 100644 --- a/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/Native/INativeFirmwareEraserCommandableProxy.cs +++ b/Laerdal.McuMgr/Shared/FirmwareEraser/Contracts/Native/INativeFirmwareEraserCommandableProxy.cs @@ -1,8 +1,10 @@ -namespace Laerdal.McuMgr.FirmwareEraser.Contracts.Native +using Laerdal.McuMgr.FirmwareEraser.Contracts.Enums; + +namespace Laerdal.McuMgr.FirmwareEraser.Contracts.Native { internal interface INativeFirmwareEraserCommandableProxy { void Disconnect(); - void BeginErasure(int imageIndex); + EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex); } } \ No newline at end of file diff --git a/Laerdal.McuMgr/Shared/FirmwareEraser/FirmwareEraser.cs b/Laerdal.McuMgr/Shared/FirmwareEraser/FirmwareEraser.cs index 1f879c0d..b53d2d2d 100644 --- a/Laerdal.McuMgr/Shared/FirmwareEraser/FirmwareEraser.cs +++ b/Laerdal.McuMgr/Shared/FirmwareEraser/FirmwareEraser.cs @@ -58,8 +58,15 @@ internal FirmwareEraser(INativeFirmwareEraserProxy nativeFirmwareEraserProxy) public string LastFatalErrorMessage => _nativeFirmwareEraserProxy?.LastFatalErrorMessage; public void Disconnect() => _nativeFirmwareEraserProxy?.Disconnect(); - public void BeginErasure(int imageIndex = 1) => _nativeFirmwareEraserProxy?.BeginErasure(imageIndex); + public EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex = 1) + { + if (_nativeFirmwareEraserProxy == null) + throw new InvalidOperationException("The native firmware eraser is not initialized"); + + return _nativeFirmwareEraserProxy.BeginErasure(imageIndex); + } + private event EventHandler _logEmitted; private event EventHandler _stateChanged; private event EventHandler _busyStateChanged; @@ -114,7 +121,9 @@ public async Task EraseAsync(int imageIndex = 1, int timeoutInMs = -1) StateChanged += FirmwareEraser_StateChanged_; FatalErrorOccurred += FirmwareEraser_FatalErrorOccurred_; - BeginErasure(imageIndex); //00 dont use task.run here for now + var verdict = BeginErasure(imageIndex); //00 dont use task.run here for now + if (verdict != EFirmwareErasureInitializationVerdict.Success) + throw new ArgumentException(verdict.ToString()); _ = timeoutInMs <= 0 ? await taskCompletionSource.Task diff --git a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Enums/EFirmwareInstallerFatalErrorType.cs b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Enums/EFirmwareInstallerFatalErrorType.cs index 6c493dd1..cfa94770 100644 --- a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Enums/EFirmwareInstallerFatalErrorType.cs +++ b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Enums/EFirmwareInstallerFatalErrorType.cs @@ -8,5 +8,6 @@ public enum EFirmwareInstallerFatalErrorType //these must mirror the enum values DeploymentFailed = 3, FirmwareImageSwapTimeout = 4, FirmwareUploadingErroredOut = 5, + FailedInstallationAlreadyInProgress = 6, } -} \ No newline at end of file +} diff --git a/Laerdal.McuMgr/iOS/DeviceResetter/DeviceResetter.cs b/Laerdal.McuMgr/iOS/DeviceResetter/DeviceResetter.cs index 5dd0233a..e1049d90 100644 --- a/Laerdal.McuMgr/iOS/DeviceResetter/DeviceResetter.cs +++ b/Laerdal.McuMgr/iOS/DeviceResetter/DeviceResetter.cs @@ -50,11 +50,16 @@ internal IOSNativeDeviceResetterProxy(CBPeripheral bluetoothDevice, INativeDevic public string LastFatalErrorMessage => _nativeDeviceResetter?.LastFatalErrorMessage; public void Disconnect() => _nativeDeviceResetter?.Disconnect(); - public void BeginReset() => _nativeDeviceResetter?.BeginReset(); - - #endregion + public EDeviceResetterInitializationVerdict BeginReset() + { + if (_nativeDeviceResetter == null) + throw new InvalidOperationException("The native device resetter is not initialized"); + + return TranslateEIOSDeviceResetterInitializationVerdict(_nativeDeviceResetter.BeginReset(keepThisDummyParameter: false)); + } + #endregion #region listener callbacks -> event emitters @@ -109,6 +114,14 @@ public void FatalErrorOccurredAdvertisement(string errorMessage, EGlobalErrorCod EIOSDeviceResetterState.Resetting => EDeviceResetterState.Resetting, _ => throw new ArgumentOutOfRangeException(nameof(state), state, "Unknown enum value") }; + + static private EDeviceResetterInitializationVerdict TranslateEIOSDeviceResetterInitializationVerdict(EIOSDeviceResetInitializationVerdict verdict) => verdict switch + { + EIOSDeviceResetInitializationVerdict.Success => EDeviceResetterInitializationVerdict.Success, + EIOSDeviceResetInitializationVerdict.FailedErrorUponCommencing => EDeviceResetterInitializationVerdict.FailedErrorUponCommencing, + EIOSDeviceResetInitializationVerdict.FailedOtherResetAlreadyInProgress => EDeviceResetterInitializationVerdict.FailedOtherResetAlreadyInProgress, + _ => throw new ArgumentOutOfRangeException(nameof(verdict), verdict, "Unknown enum value") + }; } } } \ No newline at end of file diff --git a/Laerdal.McuMgr/iOS/FirmwareEraser/FirmwareEraser.cs b/Laerdal.McuMgr/iOS/FirmwareEraser/FirmwareEraser.cs index 0aa0703f..4a7942aa 100644 --- a/Laerdal.McuMgr/iOS/FirmwareEraser/FirmwareEraser.cs +++ b/Laerdal.McuMgr/iOS/FirmwareEraser/FirmwareEraser.cs @@ -50,7 +50,13 @@ internal IOSNativeFirmwareEraserProxy(CBPeripheral bluetoothDevice, INativeFirmw public void Disconnect() => _nativeFirmwareEraser?.Disconnect(); //we are simply forwarding the commands down to the native world of ios here public string LastFatalErrorMessage => _nativeFirmwareEraser?.LastFatalErrorMessage; - public void BeginErasure(int imageIndex) => _nativeFirmwareEraser?.BeginErasure(imageIndex); + public EFirmwareErasureInitializationVerdict BeginErasure(int imageIndex) + { + if (_nativeFirmwareEraser == null) + throw new InvalidOperationException("The native firmware eraser is not initialized"); + + return TranslateEIOSFirmwareErasureInitializationVerdict(_nativeFirmwareEraser.BeginErasure(imageIndex)); + } #endregion @@ -108,6 +114,14 @@ public void FatalErrorOccurredAdvertisement(string errorMessage, EGlobalErrorCod EIOSFirmwareEraserState.Complete => EFirmwareErasureState.Complete, _ => throw new ArgumentOutOfRangeException(nameof(state), state, "Unknown enum value") }; + + static private EFirmwareErasureInitializationVerdict TranslateEIOSFirmwareErasureInitializationVerdict(EIOSFirmwareErasureInitializationVerdict verdict) => verdict switch + { + EIOSFirmwareErasureInitializationVerdict.Success => EFirmwareErasureInitializationVerdict.Success, + EIOSFirmwareErasureInitializationVerdict.FailedErrorUponCommencing => EFirmwareErasureInitializationVerdict.FailedErrorUponCommencing, + EIOSFirmwareErasureInitializationVerdict.FailedOtherErasureAlreadyInProgress => EFirmwareErasureInitializationVerdict.FailedOtherErasureAlreadyInProgress, + _ => throw new ArgumentOutOfRangeException(nameof(verdict), verdict, "Unknown enum value") + }; } } } \ No newline at end of file diff --git a/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs b/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs index 14662145..4d5b06fa 100644 --- a/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs +++ b/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs @@ -113,6 +113,9 @@ public EFirmwareInstallationVerdict BeginInstallation( int? byteAlignment = null ) { + if (_nativeFirmwareInstaller == null) + throw new InvalidOperationException("The native firmware installer is not initialized"); + var nsDataOfFirmware = NSData.FromArray(data); var verdict = TranslateFirmwareInstallationVerdict(_nativeFirmwareInstaller.BeginInstallation( @@ -217,6 +220,8 @@ static private EFirmwareInstallerFatalErrorType TranslateEIOSFirmwareInstallerFa EIOSFirmwareInstallerFatalErrorType.DeploymentFailed => EFirmwareInstallerFatalErrorType.DeploymentFailed, EIOSFirmwareInstallerFatalErrorType.FirmwareImageSwapTimeout => EFirmwareInstallerFatalErrorType.FirmwareImageSwapTimeout, EIOSFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut => EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, + EIOSFirmwareInstallerFatalErrorType.FailedInstallationAlreadyInProgress => EFirmwareInstallerFatalErrorType.FailedInstallationAlreadyInProgress, + _ => throw new ArgumentOutOfRangeException(nameof(fatalErrorType), actualValue: fatalErrorType, message: "Unknown enum value") }; }