diff --git a/homeassistant/components/homeassistant_hardware/firmware_config_flow.py b/homeassistant/components/homeassistant_hardware/firmware_config_flow.py
index a91fb00c142d07b5ded696fd7f79b0c22db701ed..fac3d2d973565bd10fc3fe1526da9fc2a3e6980a 100644
--- a/homeassistant/components/homeassistant_hardware/firmware_config_flow.py
+++ b/homeassistant/components/homeassistant_hardware/firmware_config_flow.py
@@ -7,17 +7,12 @@ import asyncio
 import logging
 from typing import Any
 
-from universal_silabs_flasher.const import ApplicationType
-
 from homeassistant.components.hassio import (
     AddonError,
     AddonInfo,
     AddonManager,
     AddonState,
 )
-from homeassistant.components.zha.repairs.wrong_silabs_firmware import (
-    probe_silabs_firmware_type,
-)
 from homeassistant.config_entries import (
     ConfigEntry,
     ConfigEntryBaseFlow,
@@ -32,9 +27,11 @@ from homeassistant.helpers.hassio import is_hassio
 from . import silabs_multiprotocol_addon
 from .const import ZHA_DOMAIN
 from .util import (
+    ApplicationType,
     get_otbr_addon_manager,
     get_zha_device_path,
     get_zigbee_flasher_addon_manager,
+    probe_silabs_firmware_type,
 )
 
 _LOGGER = logging.getLogger(__name__)
diff --git a/homeassistant/components/homeassistant_hardware/manifest.json b/homeassistant/components/homeassistant_hardware/manifest.json
index f692094bc67c2e69e7e12bca74552124078269cb..2efa12ccfda9fa50e9df90a34e1a5533afed2863 100644
--- a/homeassistant/components/homeassistant_hardware/manifest.json
+++ b/homeassistant/components/homeassistant_hardware/manifest.json
@@ -1,8 +1,9 @@
 {
   "domain": "homeassistant_hardware",
   "name": "Home Assistant Hardware",
-  "after_dependencies": ["hassio", "zha"],
+  "after_dependencies": ["hassio"],
   "codeowners": ["@home-assistant/core"],
   "documentation": "https://www.home-assistant.io/integrations/homeassistant_hardware",
-  "integration_type": "system"
+  "integration_type": "system",
+  "requirements": ["universal-silabs-flasher==0.0.25"]
 }
diff --git a/homeassistant/components/homeassistant_hardware/util.py b/homeassistant/components/homeassistant_hardware/util.py
index 0c06ff05e5cf83c9951dbc283b9eb81dfb1ff11b..3fd5bc60037286d79b927857f1bddcbbf45385f2 100644
--- a/homeassistant/components/homeassistant_hardware/util.py
+++ b/homeassistant/components/homeassistant_hardware/util.py
@@ -3,11 +3,14 @@
 from __future__ import annotations
 
 from collections import defaultdict
+from collections.abc import Iterable
 from dataclasses import dataclass
+from enum import StrEnum
 import logging
 from typing import cast
 
-from universal_silabs_flasher.const import ApplicationType
+from universal_silabs_flasher.const import ApplicationType as FlasherApplicationType
+from universal_silabs_flasher.flasher import Flasher
 
 from homeassistant.components.hassio import AddonError, AddonState
 from homeassistant.config_entries import ConfigEntry, ConfigEntryState
@@ -32,6 +35,26 @@ from .silabs_multiprotocol_addon import (
 _LOGGER = logging.getLogger(__name__)
 
 
+class ApplicationType(StrEnum):
+    """Application type running on a device."""
+
+    GECKO_BOOTLOADER = "bootloader"
+    CPC = "cpc"
+    EZSP = "ezsp"
+    SPINEL = "spinel"
+
+    @classmethod
+    def from_flasher_application_type(
+        cls, app_type: FlasherApplicationType
+    ) -> ApplicationType:
+        """Convert a USF application type enum."""
+        return cls(app_type.value)
+
+    def as_flasher_application_type(self) -> FlasherApplicationType:
+        """Convert the application type enum into one compatible with USF."""
+        return FlasherApplicationType(self.value)
+
+
 def get_zha_device_path(config_entry: ConfigEntry) -> str | None:
     """Get the device path from a ZHA config entry."""
     return cast(str | None, config_entry.data.get("device", {}).get("path", None))
@@ -137,3 +160,27 @@ async def guess_firmware_type(hass: HomeAssistant, device_path: str) -> Firmware
     assert guesses
 
     return guesses[-1]
+
+
+async def probe_silabs_firmware_type(
+    device: str, *, probe_methods: Iterable[ApplicationType] | None = None
+) -> ApplicationType | None:
+    """Probe the running firmware on a Silabs device."""
+    flasher = Flasher(
+        device=device,
+        **(
+            {"probe_methods": [m.as_flasher_application_type() for m in probe_methods]}
+            if probe_methods
+            else {}
+        ),
+    )
+
+    try:
+        await flasher.probe_app_type()
+    except Exception:  # noqa: BLE001
+        _LOGGER.debug("Failed to probe application type", exc_info=True)
+
+    if flasher.app_type is None:
+        return None
+
+    return ApplicationType.from_flasher_application_type(flasher.app_type)
diff --git a/homeassistant/components/homeassistant_sky_connect/config_flow.py b/homeassistant/components/homeassistant_sky_connect/config_flow.py
index 5c35732312be2943cdab4b4c2d08158dc3556c16..2fbf8bcb6bcf5592e890fbf7385355b4e26ff887 100644
--- a/homeassistant/components/homeassistant_sky_connect/config_flow.py
+++ b/homeassistant/components/homeassistant_sky_connect/config_flow.py
@@ -5,13 +5,12 @@ from __future__ import annotations
 import logging
 from typing import TYPE_CHECKING, Any, Protocol
 
-from universal_silabs_flasher.const import ApplicationType
-
 from homeassistant.components import usb
 from homeassistant.components.homeassistant_hardware import (
     firmware_config_flow,
     silabs_multiprotocol_addon,
 )
+from homeassistant.components.homeassistant_hardware.util import ApplicationType
 from homeassistant.config_entries import (
     ConfigEntry,
     ConfigEntryBaseFlow,
diff --git a/homeassistant/components/homeassistant_yellow/config_flow.py b/homeassistant/components/homeassistant_yellow/config_flow.py
index 2c58ecdfc1c12ee1e783eba3310bdb68d149da23..502a20db07c290cd0c4de3d0e2bac20e95687653 100644
--- a/homeassistant/components/homeassistant_yellow/config_flow.py
+++ b/homeassistant/components/homeassistant_yellow/config_flow.py
@@ -8,7 +8,6 @@ import logging
 from typing import Any, final
 
 import aiohttp
-from universal_silabs_flasher.const import ApplicationType
 import voluptuous as vol
 
 from homeassistant.components.hassio import (
@@ -25,6 +24,7 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
     OptionsFlowHandler as MultiprotocolOptionsFlowHandler,
     SerialPortSettings as MultiprotocolSerialPortSettings,
 )
+from homeassistant.components.homeassistant_hardware.util import ApplicationType
 from homeassistant.config_entries import (
     SOURCE_HARDWARE,
     ConfigEntry,
diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json
index 45d8f6bb25f9e6a8d478f2b0dc6d4d8975b0dcc9..28d5f601671fff67de789371fd76291c5ca1c276 100644
--- a/homeassistant/components/zha/manifest.json
+++ b/homeassistant/components/zha/manifest.json
@@ -4,7 +4,7 @@
   "after_dependencies": ["hassio", "onboarding", "usb"],
   "codeowners": ["@dmulcahey", "@adminiuga", "@puddly", "@TheJulianJES"],
   "config_flow": true,
-  "dependencies": ["file_upload"],
+  "dependencies": ["file_upload", "homeassistant_hardware"],
   "documentation": "https://www.home-assistant.io/integrations/zha",
   "iot_class": "local_polling",
   "loggers": [
@@ -21,7 +21,7 @@
     "zha",
     "universal_silabs_flasher"
   ],
-  "requirements": ["universal-silabs-flasher==0.0.25", "zha==0.0.44"],
+  "requirements": ["zha==0.0.44"],
   "usb": [
     {
       "vid": "10C4",
diff --git a/homeassistant/components/zha/repairs/wrong_silabs_firmware.py b/homeassistant/components/zha/repairs/wrong_silabs_firmware.py
index 4d6d1ae52d86212ad41df0efee0b988c6a282bd9..566158eff560254067f15d80e4370a2d07fbee31 100644
--- a/homeassistant/components/zha/repairs/wrong_silabs_firmware.py
+++ b/homeassistant/components/zha/repairs/wrong_silabs_firmware.py
@@ -5,9 +5,10 @@ from __future__ import annotations
 import enum
 import logging
 
-from universal_silabs_flasher.const import ApplicationType
-from universal_silabs_flasher.flasher import Flasher
-
+from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
+    probe_silabs_firmware_type,
+)
 from homeassistant.components.homeassistant_sky_connect import (
     hardware as skyconnect_hardware,
 )
@@ -74,23 +75,6 @@ def _detect_radio_hardware(hass: HomeAssistant, device: str) -> HardwareType:
     return HardwareType.OTHER
 
 
-async def probe_silabs_firmware_type(
-    device: str, *, probe_methods: ApplicationType | None = None
-) -> ApplicationType | None:
-    """Probe the running firmware on a Silabs device."""
-    flasher = Flasher(
-        device=device,
-        **({"probe_methods": probe_methods} if probe_methods else {}),
-    )
-
-    try:
-        await flasher.probe_app_type()
-    except Exception:  # noqa: BLE001
-        _LOGGER.debug("Failed to probe application type", exc_info=True)
-
-    return flasher.app_type
-
-
 async def warn_on_wrong_silabs_firmware(hass: HomeAssistant, device: str) -> bool:
     """Create a repair issue if the wrong type of SiLabs firmware is detected."""
     # Only consider actual serial ports
diff --git a/requirements_all.txt b/requirements_all.txt
index dbaefdc3ebefecc7c7498f861b6096718d613aef..f6bbe93da0840930e1102733cadca75b4620660f 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -2942,7 +2942,7 @@ unifi_ap==0.0.2
 # homeassistant.components.unifiled
 unifiled==0.11
 
-# homeassistant.components.zha
+# homeassistant.components.homeassistant_hardware
 universal-silabs-flasher==0.0.25
 
 # homeassistant.components.upb
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 2c43f82df54e45761303784dad2f09fd52c1ea3f..cea3c39c1458b1557491028f78835017b2a271b0 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -2358,9 +2358,6 @@ ultraheat-api==0.5.7
 # homeassistant.components.unifiprotect
 unifi-discovery==1.2.0
 
-# homeassistant.components.zha
-universal-silabs-flasher==0.0.25
-
 # homeassistant.components.upb
 upb-lib==0.5.9
 
diff --git a/script/hassfest/dependencies.py b/script/hassfest/dependencies.py
index 62644e19c5e6c84fa26304ec4e53026338cad44d..d29571eaa83b4893ee26e0a86fd4db60077e169f 100644
--- a/script/hassfest/dependencies.py
+++ b/script/hassfest/dependencies.py
@@ -168,6 +168,7 @@ IGNORE_VIOLATIONS = {
     ("zha", "homeassistant_sky_connect"),
     ("zha", "homeassistant_yellow"),
     ("homeassistant_sky_connect", "zha"),
+    ("homeassistant_hardware", "zha"),
     # This should become a helper method that integrations can submit data to
     ("websocket_api", "lovelace"),
     ("websocket_api", "shopping_list"),
diff --git a/tests/components/homeassistant_hardware/test_config_flow.py b/tests/components/homeassistant_hardware/test_config_flow.py
index 8b0995a67f392cc0eabaf8597e5651d377ed81c5..145087073af7c6b1983da17581c0308320d0f54b 100644
--- a/tests/components/homeassistant_hardware/test_config_flow.py
+++ b/tests/components/homeassistant_hardware/test_config_flow.py
@@ -7,7 +7,6 @@ from typing import Any
 from unittest.mock import AsyncMock, Mock, call, patch
 
 import pytest
-from universal_silabs_flasher.const import ApplicationType
 
 from homeassistant.components.hassio import AddonInfo, AddonState
 from homeassistant.components.homeassistant_hardware.firmware_config_flow import (
@@ -17,6 +16,7 @@ from homeassistant.components.homeassistant_hardware.firmware_config_flow import
     BaseFirmwareOptionsFlow,
 )
 from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
     get_otbr_addon_manager,
     get_zigbee_flasher_addon_manager,
 )
diff --git a/tests/components/homeassistant_hardware/test_config_flow_failures.py b/tests/components/homeassistant_hardware/test_config_flow_failures.py
index 5a6f765c44ccb84c91e4af58a700482875570ba9..f5375fb51ddd9fcaae6418a6d3e7d38ee2139672 100644
--- a/tests/components/homeassistant_hardware/test_config_flow_failures.py
+++ b/tests/components/homeassistant_hardware/test_config_flow_failures.py
@@ -3,13 +3,13 @@
 from unittest.mock import AsyncMock
 
 import pytest
-from universal_silabs_flasher.const import ApplicationType
 
 from homeassistant.components.hassio import AddonError, AddonInfo, AddonState
 from homeassistant.components.homeassistant_hardware.firmware_config_flow import (
     STEP_PICK_FIRMWARE_THREAD,
     STEP_PICK_FIRMWARE_ZIGBEE,
 )
+from homeassistant.components.homeassistant_hardware.util import ApplicationType
 from homeassistant.core import HomeAssistant
 from homeassistant.data_entry_flow import FlowResultType
 
diff --git a/tests/components/homeassistant_hardware/test_util.py b/tests/components/homeassistant_hardware/test_util.py
index 4a30a39686f629762c2266b34430de1f1a58e4c6..3f019a0409cbef8ff927ff0fb93f4bd1b2ab02c7 100644
--- a/tests/components/homeassistant_hardware/test_util.py
+++ b/tests/components/homeassistant_hardware/test_util.py
@@ -2,13 +2,14 @@
 
 from unittest.mock import AsyncMock, patch
 
-from universal_silabs_flasher.const import ApplicationType
-
 from homeassistant.components.hassio import AddonError, AddonInfo, AddonState
 from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
     FirmwareGuess,
+    FlasherApplicationType,
     get_zha_device_path,
     guess_firmware_type,
+    probe_silabs_firmware_type,
 )
 from homeassistant.config_entries import ConfigEntryState
 from homeassistant.core import HomeAssistant
@@ -156,3 +157,27 @@ async def test_guess_firmware_type(hass: HomeAssistant) -> None:
         assert (await guess_firmware_type(hass, path)) == FirmwareGuess(
             is_running=True, firmware_type=ApplicationType.CPC, source="multiprotocol"
         )
+
+
+async def test_probe_silabs_firmware_type() -> None:
+    """Test probing Silabs firmware type."""
+
+    with patch(
+        "homeassistant.components.homeassistant_hardware.util.Flasher.probe_app_type",
+        side_effect=RuntimeError,
+    ):
+        assert (await probe_silabs_firmware_type("/dev/ttyUSB0")) is None
+
+    with patch(
+        "homeassistant.components.homeassistant_hardware.util.Flasher.probe_app_type",
+        side_effect=lambda self: setattr(self, "app_type", FlasherApplicationType.EZSP),
+        autospec=True,
+    ) as mock_probe_app_type:
+        # The application type constant is converted back and forth transparently
+        result = await probe_silabs_firmware_type(
+            "/dev/ttyUSB0", probe_methods=[ApplicationType.EZSP]
+        )
+        assert result is ApplicationType.EZSP
+
+        flasher = mock_probe_app_type.mock_calls[0].args[0]
+        assert flasher._probe_methods == [FlasherApplicationType.EZSP]
diff --git a/tests/components/homeassistant_sky_connect/test_init.py b/tests/components/homeassistant_sky_connect/test_init.py
index e1c13771fdcca18708661532c9bd35049f976e6f..15eeb205537087633412edbae20d5db7822538a5 100644
--- a/tests/components/homeassistant_sky_connect/test_init.py
+++ b/tests/components/homeassistant_sky_connect/test_init.py
@@ -2,9 +2,10 @@
 
 from unittest.mock import patch
 
-from universal_silabs_flasher.const import ApplicationType
-
-from homeassistant.components.homeassistant_hardware.util import FirmwareGuess
+from homeassistant.components.homeassistant_hardware.util import (
+    ApplicationType,
+    FirmwareGuess,
+)
 from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
 from homeassistant.core import HomeAssistant
 
diff --git a/tests/components/zha/test_repairs.py b/tests/components/zha/test_repairs.py
index c2925161748ce3eb60f44c9fc2c3e2ddce984a69..af81ac0d586a58503bf74f75bc5e48bd720aae59 100644
--- a/tests/components/zha/test_repairs.py
+++ b/tests/components/zha/test_repairs.py
@@ -1,17 +1,14 @@
 """Test ZHA repairs."""
 
-from collections.abc import Callable
 from http import HTTPStatus
-import logging
 from unittest.mock import Mock, call, patch
 
 import pytest
-from universal_silabs_flasher.const import ApplicationType
-from universal_silabs_flasher.flasher import Flasher
 from zigpy.application import ControllerApplication
 import zigpy.backups
 from zigpy.exceptions import NetworkSettingsInconsistent
 
+from homeassistant.components.homeassistant_hardware.util import ApplicationType
 from homeassistant.components.homeassistant_sky_connect.const import (  # pylint: disable=hass-component-root-import
     DOMAIN as SKYCONNECT_DOMAIN,
 )
@@ -25,7 +22,6 @@ from homeassistant.components.zha.repairs.wrong_silabs_firmware import (
     ISSUE_WRONG_SILABS_FIRMWARE_INSTALLED,
     HardwareType,
     _detect_radio_hardware,
-    probe_silabs_firmware_type,
     warn_on_wrong_silabs_firmware,
 )
 from homeassistant.config_entries import ConfigEntryState
@@ -41,15 +37,6 @@ SKYCONNECT_DEVICE = "/dev/serial/by-id/usb-Nabu_Casa_SkyConnect_v1.0_9e2adbd75b8
 CONNECT_ZBT1_DEVICE = "/dev/serial/by-id/usb-Nabu_Casa_Home_Assistant_Connect_ZBT-1_9e2adbd75b8beb119fe564a0f320645d-if00-port0"
 
 
-def set_flasher_app_type(app_type: ApplicationType) -> Callable[[Flasher], None]:
-    """Set the app type on the flasher."""
-
-    def replacement(self: Flasher) -> None:
-        self.app_type = app_type
-
-    return replacement
-
-
 def test_detect_radio_hardware(hass: HomeAssistant) -> None:
     """Test logic to detect radio hardware."""
     skyconnect_config_entry = MockConfigEntry(
@@ -143,9 +130,8 @@ async def test_multipan_firmware_repair(
     # ZHA fails to set up
     with (
         patch(
-            "homeassistant.components.zha.repairs.wrong_silabs_firmware.Flasher.probe_app_type",
-            side_effect=set_flasher_app_type(ApplicationType.CPC),
-            autospec=True,
+            "homeassistant.components.zha.repairs.wrong_silabs_firmware.probe_silabs_firmware_type",
+            return_value=ApplicationType.CPC,
         ),
         patch(
             "homeassistant.components.zha.Gateway.async_initialize",
@@ -194,9 +180,8 @@ async def test_multipan_firmware_no_repair_on_probe_failure(
     # ZHA fails to set up
     with (
         patch(
-            "homeassistant.components.zha.repairs.wrong_silabs_firmware.Flasher.probe_app_type",
-            side_effect=set_flasher_app_type(None),
-            autospec=True,
+            "homeassistant.components.zha.repairs.wrong_silabs_firmware.probe_silabs_firmware_type",
+            return_value=None,
         ),
         patch(
             "homeassistant.components.zha.Gateway.async_initialize",
@@ -231,9 +216,8 @@ async def test_multipan_firmware_retry_on_probe_ezsp(
     # ZHA fails to set up
     with (
         patch(
-            "homeassistant.components.zha.repairs.wrong_silabs_firmware.Flasher.probe_app_type",
-            side_effect=set_flasher_app_type(ApplicationType.EZSP),
-            autospec=True,
+            "homeassistant.components.zha.repairs.wrong_silabs_firmware.probe_silabs_firmware_type",
+            return_value=ApplicationType.EZSP,
         ),
         patch(
             "homeassistant.components.zha.Gateway.async_initialize",
@@ -260,37 +244,12 @@ async def test_no_warn_on_socket(hass: HomeAssistant) -> None:
     """Test that no warning is issued when the device is a socket."""
     with patch(
         "homeassistant.components.zha.repairs.wrong_silabs_firmware.probe_silabs_firmware_type",
-        autospec=True,
     ) as mock_probe:
         await warn_on_wrong_silabs_firmware(hass, device="socket://1.2.3.4:5678")
 
     mock_probe.assert_not_called()
 
 
-async def test_probe_failure_exception_handling(
-    caplog: pytest.LogCaptureFixture,
-) -> None:
-    """Test that probe failures are handled gracefully."""
-    logger = logging.getLogger(
-        "homeassistant.components.zha.repairs.wrong_silabs_firmware"
-    )
-    orig_level = logger.level
-
-    with (
-        caplog.at_level(logging.DEBUG),
-        patch(
-            "homeassistant.components.zha.repairs.wrong_silabs_firmware.Flasher.probe_app_type",
-            side_effect=RuntimeError(),
-        ) as mock_probe_app_type,
-    ):
-        logger.setLevel(logging.DEBUG)
-        await probe_silabs_firmware_type("/dev/ttyZigbee")
-        logger.setLevel(orig_level)
-
-    mock_probe_app_type.assert_awaited()
-    assert "Failed to probe application type" in caplog.text
-
-
 async def test_inconsistent_settings_keep_new(
     hass: HomeAssistant,
     hass_client: ClientSessionGenerator,