diff --git a/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateManager.kt b/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateManager.kt index ea178dac3..70a25a5e2 100644 --- a/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateManager.kt +++ b/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateManager.kt @@ -63,7 +63,12 @@ constructor( fun dfuProgressFlow(): Flow = nordicDfuHandler.progressFlow() private fun getHandler(hardware: DeviceHardware): FirmwareUpdateHandler = when { - radioPrefs.isSerial() -> usbUpdateHandler + radioPrefs.isSerial() -> { + if (isEsp32Architecture(hardware.architecture)) { + error("Serial/USB firmware update not supported for ESP32 devices from the app") + } + usbUpdateHandler + } radioPrefs.isBle() -> { if (isEsp32Architecture(hardware.architecture)) { esp32OtaUpdateHandler diff --git a/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateViewModel.kt b/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateViewModel.kt index d57d8999e..c60cc7a76 100644 --- a/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateViewModel.kt +++ b/feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateViewModel.kt @@ -147,6 +147,7 @@ constructor( checkForUpdates() } + @Suppress("LongMethod") fun checkForUpdates() { updateJob?.cancel() updateJob = @@ -174,14 +175,18 @@ constructor( _selectedRelease.value = release val dismissed = bootloaderWarningDataSource.isDismissed(address) val firmwareUpdateMethod = - if (radioPrefs.isSerial()) { - FirmwareUpdateMethod.Usb - } else if (radioPrefs.isBle()) { - FirmwareUpdateMethod.Ble - } else if (radioPrefs.isTcp()) { - FirmwareUpdateMethod.Wifi - } else { - FirmwareUpdateMethod.Unknown + when { + radioPrefs.isSerial() -> { + // ESP32 Serial updates are not supported from the app yet. + if (deviceHardware.isEsp32Arc) { + FirmwareUpdateMethod.Unknown + } else { + FirmwareUpdateMethod.Usb + } + } + radioPrefs.isBle() -> FirmwareUpdateMethod.Ble + radioPrefs.isTcp() -> FirmwareUpdateMethod.Wifi + else -> FirmwareUpdateMethod.Unknown } _state.value = FirmwareUpdateState.Ready( diff --git a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsViewModel.kt index 2fe9d325c..225c8d1c3 100644 --- a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsViewModel.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsViewModel.kt @@ -128,14 +128,18 @@ constructor( } else if (radioPrefs.isBle() || radioPrefs.isSerial() || radioPrefs.isTcp()) { val hwModel = node.user.hwModel.number val hw = deviceHardwareRepository.getDeviceHardwareByModel(hwModel).getOrNull() - // Support both Nordic DFU (requiresDfu) and ESP32 Unified OTA (supportsUnifiedOta) val capabilities = Capabilities(node.metadata?.firmwareVersion) + val isSerial = radioPrefs.isSerial() // ESP32 Unified OTA is only supported via BLE or WiFi (TCP), not USB Serial. - val isEsp32OtaSupported = - hw?.isEsp32Arc == true && capabilities.supportsEsp32Ota && !radioPrefs.isSerial() + val isEsp32OtaSupported = hw?.isEsp32Arc == true && capabilities.supportsEsp32Ota && !isSerial - flow { emit(hw?.requiresDfu == true || isEsp32OtaSupported) } + // Nordic DFU/USB update is supported for NRF52/RP2040. + // For ESP32, we do NOT support Serial updates from the app yet, even if requiresDfu is true + // (which might be set for S3 native USB, but is currently unused by our handlers). + val isDfuSupported = hw?.requiresDfu == true && hw.isEsp32Arc != true + + flow { emit(isDfuSupported || isEsp32OtaSupported) } } else { flowOf(false) }