diff --git a/homeassistant/components/homeassistant_hardware/firmware_config_flow.py b/homeassistant/components/homeassistant_hardware/firmware_config_flow.py
index 8d7a302e7864a9569e89ecfe27ea33164803d3e1..83031587712c73ed97c4ae751575995782d6d0a2 100644
--- a/homeassistant/components/homeassistant_hardware/firmware_config_flow.py
+++ b/homeassistant/components/homeassistant_hardware/firmware_config_flow.py
@@ -28,12 +28,13 @@ from . import silabs_multiprotocol_addon
 from .const import OTBR_DOMAIN, ZHA_DOMAIN
 from .util import (
     ApplicationType,
+    FirmwareInfo,
     OwningAddon,
     OwningIntegration,
     get_otbr_addon_manager,
     get_zigbee_flasher_addon_manager,
     guess_hardware_owners,
-    probe_silabs_firmware_type,
+    probe_silabs_firmware_info,
 )
 
 _LOGGER = logging.getLogger(__name__)
@@ -52,7 +53,7 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
         """Instantiate base flow."""
         super().__init__(*args, **kwargs)
 
-        self._probed_firmware_type: ApplicationType | None = None
+        self._probed_firmware_info: FirmwareInfo | None = None
         self._device: str | None = None  # To be set in a subclass
         self._hardware_name: str = "unknown"  # To be set in a subclass
 
@@ -64,8 +65,8 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
         """Shared translation placeholders."""
         placeholders = {
             "firmware_type": (
-                self._probed_firmware_type.value
-                if self._probed_firmware_type is not None
+                self._probed_firmware_info.firmware_type.value
+                if self._probed_firmware_info is not None
                 else "unknown"
             ),
             "model": self._hardware_name,
@@ -120,39 +121,49 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
             description_placeholders=self._get_translation_placeholders(),
         )
 
-    async def _probe_firmware_type(self) -> bool:
+    async def _probe_firmware_info(
+        self,
+        probe_methods: tuple[ApplicationType, ...] = (
+            # We probe in order of frequency: Zigbee, Thread, then multi-PAN
+            ApplicationType.GECKO_BOOTLOADER,
+            ApplicationType.EZSP,
+            ApplicationType.SPINEL,
+            ApplicationType.CPC,
+        ),
+    ) -> bool:
         """Probe the firmware currently on the device."""
         assert self._device is not None
 
-        self._probed_firmware_type = await probe_silabs_firmware_type(
+        self._probed_firmware_info = await probe_silabs_firmware_info(
             self._device,
-            probe_methods=(
-                # We probe in order of frequency: Zigbee, Thread, then multi-PAN
-                ApplicationType.GECKO_BOOTLOADER,
+            probe_methods=probe_methods,
+        )
+
+        return (
+            self._probed_firmware_info is not None
+            and self._probed_firmware_info.firmware_type
+            in (
                 ApplicationType.EZSP,
                 ApplicationType.SPINEL,
                 ApplicationType.CPC,
-            ),
-        )
-
-        return self._probed_firmware_type in (
-            ApplicationType.EZSP,
-            ApplicationType.SPINEL,
-            ApplicationType.CPC,
+            )
         )
 
     async def async_step_pick_firmware_zigbee(
         self, user_input: dict[str, Any] | None = None
     ) -> ConfigFlowResult:
         """Pick Zigbee firmware."""
-        if not await self._probe_firmware_type():
+        if not await self._probe_firmware_info():
             return self.async_abort(
                 reason="unsupported_firmware",
                 description_placeholders=self._get_translation_placeholders(),
             )
 
         # Allow the stick to be used with ZHA without flashing
-        if self._probed_firmware_type == ApplicationType.EZSP:
+        if (
+            self._probed_firmware_info is not None
+            and self._probed_firmware_info.firmware_type == ApplicationType.EZSP
+        ):
             return await self.async_step_confirm_zigbee()
 
         if not is_hassio(self.hass):
@@ -338,7 +349,12 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
         """Confirm Zigbee setup."""
         assert self._device is not None
         assert self._hardware_name is not None
-        self._probed_firmware_type = ApplicationType.EZSP
+
+        if not await self._probe_firmware_info(probe_methods=(ApplicationType.EZSP,)):
+            return self.async_abort(
+                reason="unsupported_firmware",
+                description_placeholders=self._get_translation_placeholders(),
+            )
 
         if user_input is not None:
             await self.hass.config_entries.flow.async_init(
@@ -366,7 +382,7 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
         self, user_input: dict[str, Any] | None = None
     ) -> ConfigFlowResult:
         """Pick Thread firmware."""
-        if not await self._probe_firmware_type():
+        if not await self._probe_firmware_info():
             return self.async_abort(
                 reason="unsupported_firmware",
                 description_placeholders=self._get_translation_placeholders(),
@@ -458,7 +474,11 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
         """Confirm OTBR setup."""
         assert self._device is not None
 
-        self._probed_firmware_type = ApplicationType.SPINEL
+        if not await self._probe_firmware_info(probe_methods=(ApplicationType.SPINEL,)):
+            return self.async_abort(
+                reason="unsupported_firmware",
+                description_placeholders=self._get_translation_placeholders(),
+            )
 
         if user_input is not None:
             # OTBR discovery is done automatically via hassio
@@ -497,14 +517,14 @@ class BaseFirmwareConfigFlow(BaseFirmwareInstallFlow, ConfigFlow):
 class BaseFirmwareOptionsFlow(BaseFirmwareInstallFlow, OptionsFlow):
     """Zigbee and Thread options flow handlers."""
 
+    _probed_firmware_info: FirmwareInfo
+
     def __init__(self, config_entry: ConfigEntry, *args: Any, **kwargs: Any) -> None:
         """Instantiate options flow."""
         super().__init__(*args, **kwargs)
 
         self._config_entry = config_entry
 
-        self._probed_firmware_type = ApplicationType(self.config_entry.data["firmware"])
-
         # Make `context` a regular dictionary
         self.context = {}
 
diff --git a/homeassistant/components/homeassistant_hardware/util.py b/homeassistant/components/homeassistant_hardware/util.py
index 0e1b56b406ebdf54423734268547e58907e127ba..1afb786369e67c6b28bc811d1b3e2c38c881d6a6 100644
--- a/homeassistant/components/homeassistant_hardware/util.py
+++ b/homeassistant/components/homeassistant_hardware/util.py
@@ -249,10 +249,10 @@ async def guess_firmware_info(hass: HomeAssistant, device_path: str) -> Firmware
     return guesses[-1][0]
 
 
-async def probe_silabs_firmware_type(
+async def probe_silabs_firmware_info(
     device: str, *, probe_methods: Iterable[ApplicationType] | None = None
-) -> ApplicationType | None:
-    """Probe the running firmware on a Silabs device."""
+) -> FirmwareInfo | None:
+    """Probe the running firmware on a SiLabs device."""
     flasher = Flasher(
         device=device,
         **(
@@ -270,4 +270,26 @@ async def probe_silabs_firmware_type(
     if flasher.app_type is None:
         return None
 
-    return ApplicationType.from_flasher_application_type(flasher.app_type)
+    return FirmwareInfo(
+        device=device,
+        firmware_type=ApplicationType.from_flasher_application_type(flasher.app_type),
+        firmware_version=(
+            flasher.app_version.orig_version
+            if flasher.app_version is not None
+            else None
+        ),
+        source="probe",
+        owners=[],
+    )
+
+
+async def probe_silabs_firmware_type(
+    device: str, *, probe_methods: Iterable[ApplicationType] | None = None
+) -> ApplicationType | None:
+    """Probe the running firmware type on a SiLabs device."""
+
+    fw_info = await probe_silabs_firmware_info(device, probe_methods=probe_methods)
+    if fw_info is None:
+        return None
+
+    return fw_info.firmware_type
diff --git a/homeassistant/components/homeassistant_sky_connect/config_flow.py b/homeassistant/components/homeassistant_sky_connect/config_flow.py
index b3b4f68ba96da342f605c35d77a5afd8d1f78065..d8446c2d3f9bd9944f3fd5989dbb1b16763c4eee 100644
--- a/homeassistant/components/homeassistant_sky_connect/config_flow.py
+++ b/homeassistant/components/homeassistant_sky_connect/config_flow.py
@@ -10,7 +10,10 @@ from homeassistant.components.homeassistant_hardware import (
     firmware_config_flow,
     silabs_multiprotocol_addon,
 )
-from homeassistant.components.homeassistant_hardware.util import ApplicationType
+from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
+    FirmwareInfo,
+)
 from homeassistant.config_entries import (
     ConfigEntry,
     ConfigEntryBaseFlow,
@@ -118,7 +121,7 @@ class HomeAssistantSkyConnectConfigFlow(
         """Create the config entry."""
         assert self._usb_info is not None
         assert self._hw_variant is not None
-        assert self._probed_firmware_type is not None
+        assert self._probed_firmware_info is not None
 
         return self.async_create_entry(
             title=self._hw_variant.full_name,
@@ -130,7 +133,7 @@ class HomeAssistantSkyConnectConfigFlow(
                 "description": self._usb_info.description,  # For backwards compatibility
                 "product": self._usb_info.description,
                 "device": self._usb_info.device,
-                "firmware": self._probed_firmware_type.value,
+                "firmware": self._probed_firmware_info.firmware_type.value,
             },
         )
 
@@ -203,18 +206,26 @@ class HomeAssistantSkyConnectOptionsFlowHandler(
         self._hardware_name = self._hw_variant.full_name
         self._device = self._usb_info.device
 
+        self._probed_firmware_info = FirmwareInfo(
+            device=self._device,
+            firmware_type=ApplicationType(self.config_entry.data["firmware"]),
+            firmware_version=None,
+            source="guess",
+            owners=[],
+        )
+
         # Regenerate the translation placeholders
         self._get_translation_placeholders()
 
     def _async_flow_finished(self) -> ConfigFlowResult:
         """Create the config entry."""
-        assert self._probed_firmware_type is not None
+        assert self._probed_firmware_info is not None
 
         self.hass.config_entries.async_update_entry(
             entry=self.config_entry,
             data={
                 **self.config_entry.data,
-                "firmware": self._probed_firmware_type.value,
+                "firmware": self._probed_firmware_info.firmware_type.value,
             },
             options=self.config_entry.options,
         )
diff --git a/homeassistant/components/homeassistant_yellow/config_flow.py b/homeassistant/components/homeassistant_yellow/config_flow.py
index 502a20db07c290cd0c4de3d0e2bac20e95687653..b916c6e46caf7567138a17903662614af07eb79a 100644
--- a/homeassistant/components/homeassistant_yellow/config_flow.py
+++ b/homeassistant/components/homeassistant_yellow/config_flow.py
@@ -24,7 +24,10 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
     OptionsFlowHandler as MultiprotocolOptionsFlowHandler,
     SerialPortSettings as MultiprotocolSerialPortSettings,
 )
-from homeassistant.components.homeassistant_hardware.util import ApplicationType
+from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
+    FirmwareInfo,
+)
 from homeassistant.config_entries import (
     SOURCE_HARDWARE,
     ConfigEntry,
@@ -79,10 +82,13 @@ class HomeAssistantYellowConfigFlow(BaseFirmwareConfigFlow, domain=DOMAIN):
     ) -> ConfigFlowResult:
         """Handle the initial step."""
         # We do not actually use any portion of `BaseFirmwareConfigFlow` beyond this
-        await self._probe_firmware_type()
+        await self._probe_firmware_info()
 
         # Kick off ZHA hardware discovery automatically if Zigbee firmware is running
-        if self._probed_firmware_type is ApplicationType.EZSP:
+        if (
+            self._probed_firmware_info is not None
+            and self._probed_firmware_info.firmware_type is ApplicationType.EZSP
+        ):
             discovery_flow.async_create_flow(
                 self.hass,
                 ZHA_DOMAIN,
@@ -98,7 +104,11 @@ class HomeAssistantYellowConfigFlow(BaseFirmwareConfigFlow, domain=DOMAIN):
             title=BOARD_NAME,
             data={
                 # Assume the firmware type is EZSP if we cannot probe it
-                FIRMWARE: (self._probed_firmware_type or ApplicationType.EZSP).value,
+                FIRMWARE: (
+                    self._probed_firmware_info.firmware_type
+                    if self._probed_firmware_info is not None
+                    else ApplicationType.EZSP
+                ).value,
             },
         )
 
@@ -264,6 +274,14 @@ class HomeAssistantYellowOptionsFlowHandler(
         self._hardware_name = BOARD_NAME
         self._device = RADIO_DEVICE
 
+        self._probed_firmware_info = FirmwareInfo(
+            device=self._device,
+            firmware_type=ApplicationType(self.config_entry.data["firmware"]),
+            firmware_version=None,
+            source="guess",
+            owners=[],
+        )
+
         # Regenerate the translation placeholders
         self._get_translation_placeholders()
 
@@ -285,13 +303,13 @@ class HomeAssistantYellowOptionsFlowHandler(
 
     def _async_flow_finished(self) -> ConfigFlowResult:
         """Create the config entry."""
-        assert self._probed_firmware_type is not None
+        assert self._probed_firmware_info is not None
 
         self.hass.config_entries.async_update_entry(
             entry=self.config_entry,
             data={
                 **self.config_entry.data,
-                FIRMWARE: self._probed_firmware_type.value,
+                FIRMWARE: self._probed_firmware_info.firmware_type.value,
             },
         )
 
diff --git a/tests/components/homeassistant_hardware/test_config_flow.py b/tests/components/homeassistant_hardware/test_config_flow.py
index 3696ea66c03a54af97649c3b7799316aa422e0f7..32c5a38123311366b5522599a78f6ee0e3bf10b2 100644
--- a/tests/components/homeassistant_hardware/test_config_flow.py
+++ b/tests/components/homeassistant_hardware/test_config_flow.py
@@ -17,6 +17,7 @@ from homeassistant.components.homeassistant_hardware.firmware_config_flow import
 )
 from homeassistant.components.homeassistant_hardware.util import (
     ApplicationType,
+    FirmwareInfo,
     get_otbr_addon_manager,
     get_zigbee_flasher_addon_manager,
 )
@@ -65,13 +66,13 @@ class FakeFirmwareConfigFlow(BaseFirmwareConfigFlow, domain=TEST_DOMAIN):
         """Create the config entry."""
         assert self._device is not None
         assert self._hardware_name is not None
-        assert self._probed_firmware_type is not None
+        assert self._probed_firmware_info is not None
 
         return self.async_create_entry(
             title=self._hardware_name,
             data={
                 "device": self._device,
-                "firmware": self._probed_firmware_type.value,
+                "firmware": self._probed_firmware_info.firmware_type.value,
                 "hardware": self._hardware_name,
             },
         )
@@ -87,18 +88,26 @@ class FakeFirmwareOptionsFlowHandler(BaseFirmwareOptionsFlow):
         self._device = self.config_entry.data["device"]
         self._hardware_name = self.config_entry.data["hardware"]
 
+        self._probed_firmware_info = FirmwareInfo(
+            device=self._device,
+            firmware_type=ApplicationType(self.config_entry.data["firmware"]),
+            firmware_version=None,
+            source="guess",
+            owners=[],
+        )
+
         # Regenerate the translation placeholders
         self._get_translation_placeholders()
 
     def _async_flow_finished(self) -> ConfigFlowResult:
         """Create the config entry."""
-        assert self._probed_firmware_type is not None
+        assert self._probed_firmware_info is not None
 
         self.hass.config_entries.async_update_entry(
             entry=self.config_entry,
             data={
                 **self.config_entry.data,
-                "firmware": self._probed_firmware_type.value,
+                "firmware": self._probed_firmware_info.firmware_type.value,
             },
             options=self.config_entry.options,
         )
@@ -142,7 +151,7 @@ def mock_addon_info(
     hass: HomeAssistant,
     *,
     is_hassio: bool = True,
-    app_type: ApplicationType = ApplicationType.EZSP,
+    app_type: ApplicationType | None = ApplicationType.EZSP,
     otbr_addon_info: AddonInfo = AddonInfo(
         available=True,
         hostname=None,
@@ -187,6 +196,17 @@ def mock_addon_info(
     )
     mock_otbr_manager.async_get_addon_info.return_value = otbr_addon_info
 
+    if app_type is None:
+        firmware_info_result = None
+    else:
+        firmware_info_result = FirmwareInfo(
+            device="/dev/ttyUSB0",  # Not used
+            firmware_type=app_type,
+            firmware_version=None,
+            owners=[],
+            source="probe",
+        )
+
     with (
         patch(
             "homeassistant.components.homeassistant_hardware.firmware_config_flow.get_otbr_addon_manager",
@@ -209,8 +229,8 @@ def mock_addon_info(
             return_value=is_hassio,
         ),
         patch(
-            "homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_type",
-            return_value=app_type,
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
+            return_value=firmware_info_result,
         ),
     ):
         yield mock_otbr_manager, mock_flasher_manager
@@ -274,10 +294,14 @@ async def test_config_flow_zigbee(hass: HomeAssistant) -> None:
         assert result["type"] is FlowResultType.FORM
         assert result["step_id"] == "confirm_zigbee"
 
-    result = await hass.config_entries.flow.async_configure(
-        result["flow_id"], user_input={}
-    )
-    assert result["type"] is FlowResultType.CREATE_ENTRY
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.EZSP,
+    ):
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.CREATE_ENTRY
 
     config_entry = result["result"]
     assert config_entry.data == {
@@ -347,10 +371,14 @@ async def test_config_flow_zigbee_skip_step_if_installed(hass: HomeAssistant) ->
         result = await hass.config_entries.flow.async_configure(result["flow_id"])
 
     # Done
-    await hass.async_block_till_done(wait_background_tasks=True)
-    result = await hass.config_entries.flow.async_configure(result["flow_id"])
-    assert result["type"] is FlowResultType.FORM
-    assert result["step_id"] == "confirm_zigbee"
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.EZSP,
+    ):
+        await hass.async_block_till_done(wait_background_tasks=True)
+        result = await hass.config_entries.flow.async_configure(result["flow_id"])
+        assert result["type"] is FlowResultType.FORM
+        assert result["step_id"] == "confirm_zigbee"
 
 
 async def test_config_flow_thread(hass: HomeAssistant) -> None:
@@ -419,17 +447,21 @@ async def test_config_flow_thread(hass: HomeAssistant) -> None:
         assert result["type"] is FlowResultType.FORM
         assert result["step_id"] == "confirm_otbr"
 
-    result = await hass.config_entries.flow.async_configure(
-        result["flow_id"], user_input={}
-    )
-    assert result["type"] is FlowResultType.CREATE_ENTRY
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.SPINEL,
+    ):
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.CREATE_ENTRY
 
-    config_entry = result["result"]
-    assert config_entry.data == {
-        "firmware": "spinel",
-        "device": TEST_DEVICE,
-        "hardware": TEST_HARDWARE_NAME,
-    }
+        config_entry = result["result"]
+        assert config_entry.data == {
+            "firmware": "spinel",
+            "device": TEST_DEVICE,
+            "hardware": TEST_HARDWARE_NAME,
+        }
 
 
 async def test_config_flow_thread_addon_already_installed(hass: HomeAssistant) -> None:
@@ -477,10 +509,14 @@ async def test_config_flow_thread_addon_already_installed(hass: HomeAssistant) -
         assert result["type"] is FlowResultType.FORM
         assert result["step_id"] == "confirm_otbr"
 
-    result = await hass.config_entries.flow.async_configure(
-        result["flow_id"], user_input={}
-    )
-    assert result["type"] is FlowResultType.CREATE_ENTRY
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.SPINEL,
+    ):
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.CREATE_ENTRY
 
 
 async def test_config_flow_zigbee_not_hassio(hass: HomeAssistant) -> None:
@@ -501,10 +537,10 @@ async def test_config_flow_zigbee_not_hassio(hass: HomeAssistant) -> None:
         assert result["type"] is FlowResultType.FORM
         assert result["step_id"] == "confirm_zigbee"
 
-    result = await hass.config_entries.flow.async_configure(
-        result["flow_id"], user_input={}
-    )
-    assert result["type"] is FlowResultType.CREATE_ENTRY
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.CREATE_ENTRY
 
     config_entry = result["result"]
     assert config_entry.data == {
@@ -538,17 +574,17 @@ async def test_options_flow_zigbee_to_thread(hass: HomeAssistant) -> None:
 
     assert await hass.config_entries.async_setup(config_entry.entry_id)
 
-    # First step is confirmation
-    result = await hass.config_entries.options.async_init(config_entry.entry_id)
-    assert result["type"] is FlowResultType.MENU
-    assert result["step_id"] == "pick_firmware"
-    assert result["description_placeholders"]["firmware_type"] == "ezsp"
-    assert result["description_placeholders"]["model"] == TEST_HARDWARE_NAME
-
     with mock_addon_info(
         hass,
         app_type=ApplicationType.EZSP,
     ) as (mock_otbr_manager, mock_flasher_manager):
+        # First step is confirmation
+        result = await hass.config_entries.options.async_init(config_entry.entry_id)
+        assert result["type"] is FlowResultType.MENU
+        assert result["step_id"] == "pick_firmware"
+        assert result["description_placeholders"]["firmware_type"] == "ezsp"
+        assert result["description_placeholders"]["model"] == TEST_HARDWARE_NAME
+
         result = await hass.config_entries.options.async_configure(
             result["flow_id"],
             user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
@@ -599,14 +635,18 @@ async def test_options_flow_zigbee_to_thread(hass: HomeAssistant) -> None:
         assert result["type"] is FlowResultType.FORM
         assert result["step_id"] == "confirm_otbr"
 
-    # We are now done
-    result = await hass.config_entries.options.async_configure(
-        result["flow_id"], user_input={}
-    )
-    assert result["type"] is FlowResultType.CREATE_ENTRY
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.SPINEL,
+    ):
+        # We are now done
+        result = await hass.config_entries.options.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.CREATE_ENTRY
 
-    # The firmware type has been updated
-    assert config_entry.data["firmware"] == "spinel"
+        # The firmware type has been updated
+        assert config_entry.data["firmware"] == "spinel"
 
 
 async def test_options_flow_thread_to_zigbee(hass: HomeAssistant) -> None:
@@ -680,11 +720,15 @@ async def test_options_flow_thread_to_zigbee(hass: HomeAssistant) -> None:
         assert result["type"] is FlowResultType.FORM
         assert result["step_id"] == "confirm_zigbee"
 
-    # We are now done
-    result = await hass.config_entries.options.async_configure(
-        result["flow_id"], user_input={}
-    )
-    assert result["type"] is FlowResultType.CREATE_ENTRY
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.EZSP,
+    ):
+        # We are now done
+        result = await hass.config_entries.options.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.CREATE_ENTRY
 
-    # The firmware type has been updated
-    assert config_entry.data["firmware"] == "ezsp"
+        # The firmware type has been updated
+        assert config_entry.data["firmware"] == "ezsp"
diff --git a/tests/components/homeassistant_hardware/test_config_flow_failures.py b/tests/components/homeassistant_hardware/test_config_flow_failures.py
index c240d0198ca77b5e893d7e39c9dc397cd785ad50..8c2ee4b90ba63da2bc3a517549db932913dd0dfa 100644
--- a/tests/components/homeassistant_hardware/test_config_flow_failures.py
+++ b/tests/components/homeassistant_hardware/test_config_flow_failures.py
@@ -309,6 +309,42 @@ async def test_config_flow_zigbee_flasher_uninstall_fails(hass: HomeAssistant) -
         assert result["step_id"] == "confirm_zigbee"
 
 
+@pytest.mark.parametrize(
+    "ignore_translations",
+    ["component.test_firmware_domain.config.abort.unsupported_firmware"],
+)
+async def test_config_flow_zigbee_confirmation_fails(hass: HomeAssistant) -> None:
+    """Test the config flow failing due to Zigbee firmware not being detected."""
+    result = await hass.config_entries.flow.async_init(
+        TEST_DOMAIN, context={"source": "hardware"}
+    )
+
+    assert result["type"] is FlowResultType.MENU
+    assert result["step_id"] == "pick_firmware"
+
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.EZSP,
+    ) as (mock_otbr_manager, mock_flasher_manager):
+        # Pick the menu option: we are now installing the addon
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"],
+            user_input={"next_step_id": STEP_PICK_FIRMWARE_ZIGBEE},
+        )
+        assert result["type"] is FlowResultType.FORM
+        assert result["step_id"] == "confirm_zigbee"
+
+    with mock_addon_info(
+        hass,
+        app_type=None,  # Probing fails
+    ) as (mock_otbr_manager, mock_flasher_manager):
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.ABORT
+        assert result["reason"] == "unsupported_firmware"
+
+
 @pytest.mark.parametrize(
     "ignore_translations",
     ["component.test_firmware_domain.config.abort.not_hassio_thread"],
@@ -530,6 +566,48 @@ async def test_config_flow_thread_flasher_uninstall_fails(hass: HomeAssistant) -
         assert result["step_id"] == "confirm_otbr"
 
 
+@pytest.mark.parametrize(
+    "ignore_translations",
+    ["component.test_firmware_domain.config.abort.unsupported_firmware"],
+)
+async def test_config_flow_thread_confirmation_fails(hass: HomeAssistant) -> None:
+    """Test the config flow failing due to OpenThread firmware not being detected."""
+    result = await hass.config_entries.flow.async_init(
+        TEST_DOMAIN, context={"source": "hardware"}
+    )
+
+    with mock_addon_info(
+        hass,
+        app_type=ApplicationType.EZSP,
+    ) as (mock_otbr_manager, mock_flasher_manager):
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"], user_input={}
+        )
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"],
+            user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
+        )
+        result = await hass.config_entries.flow.async_configure(result["flow_id"])
+        await hass.async_block_till_done(wait_background_tasks=True)
+
+        result = await hass.config_entries.flow.async_configure(result["flow_id"])
+        await hass.async_block_till_done(wait_background_tasks=True)
+
+        result = await hass.config_entries.flow.async_configure(result["flow_id"])
+        assert result["type"] is FlowResultType.FORM
+        assert result["step_id"] == "confirm_otbr"
+
+    with mock_addon_info(
+        hass,
+        app_type=None,  # Probing fails
+    ) as (mock_otbr_manager, mock_flasher_manager):
+        result = await hass.config_entries.flow.async_configure(
+            result["flow_id"], user_input={}
+        )
+        assert result["type"] is FlowResultType.ABORT
+        assert result["reason"] == "unsupported_firmware"
+
+
 @pytest.mark.parametrize(
     "ignore_translations",
     ["component.test_firmware_domain.options.abort.zha_still_using_stick"],
diff --git a/tests/components/homeassistant_hardware/test_util.py b/tests/components/homeassistant_hardware/test_util.py
index 52739f1688628132626d64a4b48657e9bde832c9..b467380c43187941f91a60a04144a29dbeddf6d1 100644
--- a/tests/components/homeassistant_hardware/test_util.py
+++ b/tests/components/homeassistant_hardware/test_util.py
@@ -2,6 +2,10 @@
 
 from unittest.mock import AsyncMock, MagicMock, patch
 
+import pytest
+from universal_silabs_flasher.common import Version as FlasherVersion
+from universal_silabs_flasher.const import ApplicationType as FlasherApplicationType
+
 from homeassistant.components.hassio import (
     AddonError,
     AddonInfo,
@@ -18,6 +22,8 @@ from homeassistant.components.homeassistant_hardware.util import (
     OwningIntegration,
     get_otbr_addon_firmware_info,
     guess_firmware_info,
+    probe_silabs_firmware_info,
+    probe_silabs_firmware_type,
 )
 from homeassistant.config_entries import ConfigEntry, ConfigEntryState
 from homeassistant.core import HomeAssistant
@@ -280,3 +286,95 @@ async def test_get_otbr_addon_firmware_info_failure_bad_options(
     )
 
     assert (await get_otbr_addon_firmware_info(hass, otbr_addon_manager)) is None
+
+
+@pytest.mark.parametrize(
+    ("app_type", "firmware_version", "expected_fw_info"),
+    [
+        (
+            FlasherApplicationType.EZSP,
+            FlasherVersion("1.0.0"),
+            FirmwareInfo(
+                device="/dev/ttyUSB0",
+                firmware_type=ApplicationType.EZSP,
+                firmware_version="1.0.0",
+                source="probe",
+                owners=[],
+            ),
+        ),
+        (
+            FlasherApplicationType.EZSP,
+            None,
+            FirmwareInfo(
+                device="/dev/ttyUSB0",
+                firmware_type=ApplicationType.EZSP,
+                firmware_version=None,
+                source="probe",
+                owners=[],
+            ),
+        ),
+        (
+            FlasherApplicationType.SPINEL,
+            FlasherVersion("2.0.0"),
+            FirmwareInfo(
+                device="/dev/ttyUSB0",
+                firmware_type=ApplicationType.SPINEL,
+                firmware_version="2.0.0",
+                source="probe",
+                owners=[],
+            ),
+        ),
+        (None, None, None),
+    ],
+)
+async def test_probe_silabs_firmware_info(
+    app_type: FlasherApplicationType | None,
+    firmware_version: FlasherVersion | None,
+    expected_fw_info: FirmwareInfo | None,
+) -> None:
+    """Test getting the firmware info."""
+
+    def probe_app_type() -> None:
+        mock_flasher.app_type = app_type
+        mock_flasher.app_version = firmware_version
+
+    mock_flasher = MagicMock()
+    mock_flasher.app_type = None
+    mock_flasher.app_version = None
+    mock_flasher.probe_app_type = AsyncMock(side_effect=probe_app_type)
+
+    with patch(
+        "homeassistant.components.homeassistant_hardware.util.Flasher",
+        return_value=mock_flasher,
+    ):
+        result = await probe_silabs_firmware_info("/dev/ttyUSB0")
+        assert result == expected_fw_info
+
+
+@pytest.mark.parametrize(
+    ("probe_result", "expected"),
+    [
+        (
+            FirmwareInfo(
+                device="/dev/ttyUSB0",
+                firmware_type=ApplicationType.EZSP,
+                firmware_version=None,
+                source="unknown",
+                owners=[],
+            ),
+            ApplicationType.EZSP,
+        ),
+        (None, None),
+    ],
+)
+async def test_probe_silabs_firmware_type(
+    probe_result: FirmwareInfo | None, expected: ApplicationType | None
+) -> None:
+    """Test getting the firmware type from the probe result."""
+    with patch(
+        "homeassistant.components.homeassistant_hardware.util.probe_silabs_firmware_info",
+        autospec=True,
+        return_value=probe_result,
+    ):
+        result = await probe_silabs_firmware_type("/dev/ttyUSB0")
+        assert result == expected
diff --git a/tests/components/homeassistant_sky_connect/test_config_flow.py b/tests/components/homeassistant_sky_connect/test_config_flow.py
index 904fcac321c7b3a9ed6780603be95075793f699a..d8542002ae862d7f4d7df252ce46e20c05f8622f 100644
--- a/tests/components/homeassistant_sky_connect/test_config_flow.py
+++ b/tests/components/homeassistant_sky_connect/test_config_flow.py
@@ -13,6 +13,10 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
     get_flasher_addon_manager,
     get_multiprotocol_addon_manager,
 )
+from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
+    FirmwareInfo,
+)
 from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
 from homeassistant.core import HomeAssistant
 from homeassistant.data_entry_flow import FlowResultType
@@ -61,10 +65,22 @@ async def test_config_flow(
     async def mock_async_step_pick_firmware_zigbee(self, data):
         return await self.async_step_confirm_zigbee(user_input={})
 
-    with patch(
-        "homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareConfigFlow.async_step_pick_firmware_zigbee",
-        autospec=True,
-        side_effect=mock_async_step_pick_firmware_zigbee,
+    with (
+        patch(
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareConfigFlow.async_step_pick_firmware_zigbee",
+            autospec=True,
+            side_effect=mock_async_step_pick_firmware_zigbee,
+        ),
+        patch(
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
+            return_value=FirmwareInfo(
+                device=usb_data.device,
+                firmware_type=ApplicationType.EZSP,
+                firmware_version=None,
+                owners=[],
+                source="probe",
+            ),
+        ),
     ):
         result = await hass.config_entries.flow.async_configure(
             result["flow_id"],
@@ -134,10 +150,22 @@ async def test_options_flow(
     async def mock_async_step_pick_firmware_zigbee(self, data):
         return await self.async_step_confirm_zigbee(user_input={})
 
-    with patch(
-        "homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
-        autospec=True,
-        side_effect=mock_async_step_pick_firmware_zigbee,
+    with (
+        patch(
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
+            autospec=True,
+            side_effect=mock_async_step_pick_firmware_zigbee,
+        ),
+        patch(
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
+            return_value=FirmwareInfo(
+                device=usb_data.device,
+                firmware_type=ApplicationType.EZSP,
+                firmware_version=None,
+                owners=[],
+                source="probe",
+            ),
+        ),
     ):
         result = await hass.config_entries.options.async_configure(
             result["flow_id"],
diff --git a/tests/components/homeassistant_yellow/test_config_flow.py b/tests/components/homeassistant_yellow/test_config_flow.py
index 1067be7b56e49288245b6327f1a72d9267848dd3..78fd45c6b5b5b757d1427c0703bf71f4fbd96900 100644
--- a/tests/components/homeassistant_yellow/test_config_flow.py
+++ b/tests/components/homeassistant_yellow/test_config_flow.py
@@ -18,7 +18,10 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
     get_flasher_addon_manager,
     get_multiprotocol_addon_manager,
 )
-from homeassistant.components.homeassistant_hardware.util import ApplicationType
+from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
+    FirmwareInfo,
+)
 from homeassistant.components.homeassistant_yellow.const import DOMAIN, RADIO_DEVICE
 from homeassistant.core import HomeAssistant
 from homeassistant.data_entry_flow import FlowResultType
@@ -82,8 +85,14 @@ async def test_config_flow(hass: HomeAssistant) -> None:
             return_value=True,
         ) as mock_setup_entry,
         patch(
-            "homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_type",
-            return_value=ApplicationType.EZSP,
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
+            return_value=FirmwareInfo(
+                device=RADIO_DEVICE,
+                firmware_type=ApplicationType.EZSP,
+                firmware_version=None,
+                owners=[],
+                source="probe",
+            ),
         ),
     ):
         result = await hass.config_entries.flow.async_init(
@@ -330,10 +339,22 @@ async def test_firmware_options_flow(hass: HomeAssistant) -> None:
     async def mock_async_step_pick_firmware_zigbee(self, data):
         return await self.async_step_confirm_zigbee(user_input={})
 
-    with patch(
-        "homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
-        autospec=True,
-        side_effect=mock_async_step_pick_firmware_zigbee,
+    with (
+        patch(
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
+            autospec=True,
+            side_effect=mock_async_step_pick_firmware_zigbee,
+        ),
+        patch(
+            "homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
+            return_value=FirmwareInfo(
+                device=RADIO_DEVICE,
+                firmware_type=ApplicationType.EZSP,
+                firmware_version=None,
+                owners=[],
+                source="probe",
+            ),
+        ),
     ):
         result = await hass.config_entries.options.async_configure(
             result["flow_id"],