Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions supervisor/docker/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,9 +474,7 @@ def mounts(self) -> list[DockerMount]:

# GPIO support
if self.app.with_gpio and self.sys_hardware.helper.support_gpio:
for gpio_path in ("/sys/class/gpio", "/sys/devices/platform/soc"):
if not Path(gpio_path).exists():
continue
for gpio_path in self.sys_hardware.helper.gpio_mount_paths:
mounts.append(
DockerMount(
type=MountType.BIND,
Expand Down
20 changes: 20 additions & 0 deletions supervisor/hardware/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@

_RE_HIDE_SYSFS: re.Pattern = re.compile(r"/sys/devices/virtual/(?:tty|block|vc)/.*")

# Candidate sysfs paths to expose to GPIO-enabled add-ons. Which subset
# exists is determined by the kernel at boot and does not change at runtime,
# so we resolve it once during hardware load.
_GPIO_CANDIDATE_PATHS: tuple[str, ...] = (
"/sys/class/gpio",
"/sys/devices/platform/soc",
)


class HwHelper(CoreSysAttributes):
"""Representation of an interface to procfs, sysfs and udev."""
Expand All @@ -26,6 +34,7 @@ def __init__(self, coresys: CoreSys):
"""Init hardware object."""
self.coresys = coresys
self._last_boot: datetime | None = None
self._gpio_mount_paths: tuple[str, ...] = ()

@property
def support_audio(self) -> bool:
Expand All @@ -37,6 +46,17 @@ def support_gpio(self) -> bool:
"""Return True if device support GPIOs."""
return bool(self.sys_hardware.filter_devices(subsystem=UdevSubsystem.GPIO))

@property
def gpio_mount_paths(self) -> tuple[str, ...]:
"""Return existing sysfs paths to mount for GPIO add-ons."""
return self._gpio_mount_paths

async def load(self) -> None:
"""Resolve hardware state that depends on blocking I/O."""
self._gpio_mount_paths = await self.sys_run_in_executor(
lambda: tuple(path for path in _GPIO_CANDIDATE_PATHS if Path(path).exists())
)

@property
def support_usb(self) -> bool:
"""Return True if the device have USB ports."""
Expand Down
1 change: 1 addition & 0 deletions supervisor/hardware/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def _import_devices(self) -> None:
async def load(self) -> None:
"""Load hardware backend."""
self._import_devices()
await self.helper.load()
await self.monitor.load()

async def unload(self) -> None:
Expand Down