From fc87af4da1e5bfef35960b2e802f79f017d8fb3e Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Tue, 21 Jul 2026 12:22:47 -0500 Subject: [PATCH] hotplug --- selfdrive/ui/mici/layouts/home.py | 2 +- selfdrive/ui/ui_state.py | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/selfdrive/ui/mici/layouts/home.py b/selfdrive/ui/mici/layouts/home.py index 55dba71b2..dbe126734 100644 --- a/selfdrive/ui/mici/layouts/home.py +++ b/selfdrive/ui/mici/layouts/home.py @@ -280,7 +280,7 @@ class MiciHomeLayout(Widget): self._version_commit_label.render() # ***** Center-aligned bottom section icons ***** - self._egpu_icon.set_visible(ui_state.usbgpu_active) + self._egpu_icon.set_visible(ui_state.usbgpu and ui_state.usbgpu_active) self._egpu_icon_gray.set_visible(ui_state.usbgpu and not ui_state.usbgpu_active) self._mic_icon.set_visible(ui_state.recording_audio) diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py index 8d6241f0e..1c41afe05 100644 --- a/selfdrive/ui/ui_state.py +++ b/selfdrive/ui/ui_state.py @@ -1,6 +1,7 @@ import json import pyray as rl import numpy as np +import socket import time import threading from collections.abc import Callable @@ -10,9 +11,12 @@ from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.params import Params from openpilot.common.swaglog import cloudlog from openpilot.selfdrive.ui.lib.prime_state import PrimeState +from openpilot.selfdrive.modeld.helpers import usbgpu_present from openpilot.system.ui.lib.application import gui_app from openpilot.system.hardware import HARDWARE, PC +NETLINK_KOBJECT_UEVENT = 15 + BACKLIGHT_OFFROAD = 65 if HARDWARE.get_device_type() == "mici" else 50 @@ -81,9 +85,20 @@ class UIState: self.is_metric: bool = self.params.get_bool("IsMetric") self.is_release = self.params.get_bool("IsReleaseBranch") self.always_on_dm: bool = self.params.get_bool("AlwaysOnDM") - self.usbgpu: bool = self.params.get_bool("UsbGpuPresent") + self.usbgpu: bool = usbgpu_present() self.usbgpu_compiled: bool = self.params.get_bool("UsbGpuCompiled") self.usbgpu_active: bool = self.params.get_bool("UsbGpuActive") + self._uevents: socket.socket | None = None + if hasattr(socket, "AF_NETLINK"): + try: + self._uevents = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + self._uevents.bind((0, 1)) + self._uevents.setblocking(False) + except OSError: + cloudlog.exception("failed to monitor USB hotplug events") + if self._uevents is not None: + self._uevents.close() + self._uevents = None self.started: bool = False self.ignition: bool = False self.recording_audio: bool = False @@ -185,7 +200,16 @@ class UIState: self.is_metric = self.params.get_bool("IsMetric") self.always_on_dm = self.params.get_bool("AlwaysOnDM") - self.usbgpu = self.params.get_bool("UsbGpuPresent") + if self._uevents is not None: + try: + while self._uevents.recv(4096): + self.usbgpu = usbgpu_present() + except BlockingIOError: + pass + except OSError: + cloudlog.exception("failed to read USB hotplug event") + self._uevents.close() + self._uevents = None self.usbgpu_compiled = self.params.get_bool("UsbGpuCompiled") self.usbgpu_active = self.params.get_bool("UsbGpuActive") self.switchback_mode_enabled = self.params_memory.get_bool("SwitchbackModeEnabled") if self.started else False