Skip to content
Merged
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
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,47 @@ For a complete list of available command-line options, please run:
gpiod-sysfs-proxy --help
```

## Integration

### systemd

The package installs a systemd template unit:

```
gpiod-sysfs-proxy@.service
```

No instance is enabled by default. The instance name is the
systemd-escaped mountpoint. To expose the compatibility filesystem at
`/run/gpio`:

```
systemctl enable --now gpiod-sysfs-proxy@run-gpio.service
```

or, to mount over `/sys/class/gpio` (only works when that directory already
exists, i.e. the kernel sysfs GPIO interface is enabled):

```
systemctl enable --now gpiod-sysfs-proxy@sys-class-gpio.service
```

You can generate the escaped instance name for any path with:

```
systemd-escape --path /run/gpio
systemd-escape --path /sys/class/gpio
```

The `sys-class-gpio` instance also works on a kernel where sysfs GPIO support
is disabled (so `/sys/class/gpio` does not exist): an instance-specific drop-in
pulls in the bundled `run-gpio-sys.mount` and `sys-class.mount` units, which
overlay the missing `gpio` directory onto `/sys/class` before the proxy starts
and tear it back down when the instance is stopped. Nothing else enables those
mounts, and they are skipped when `/sys/class/gpio` already exists. See the
[Non-existent `/sys/class/gpio`](#non-existent-sysclassgpio) caveat below for
the underlying mechanism.

## Caveats

Due to how FUSE works, there are certain limitations to the level of
Expand Down
18 changes: 18 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ authors = [
Homepage = "https://github.com/brgl/gpiod-sysfs-proxy"
Issues = "https://github.com/brgl/gpiod-sysfs-proxy/issues"

[tool.setuptools.data-files]
# Install the systemd template unit but do not enable any instance by default.
# The admin enables the mountpoint they want, e.g.:
# systemctl enable --now gpiod-sysfs-proxy@run-gpio.service
#
# The .mount units provide the /sys/class overlay needed to expose
# /sys/class/gpio on kernels where the sysfs GPIO interface is disabled. They
# are inert until pulled in: only the sys-class-gpio instance requires them
# (via the drop-in below) and they carry ConditionPathExists=!/sys/class/gpio.
"lib/systemd/system" = [
"share/gpiod-sysfs-proxy@.service",
"share/run-gpio-sys.mount",
"share/sys-class.mount",
]
"lib/systemd/system/gpiod-sysfs-proxy@sys-class-gpio.service.d" = [
"share/gpiod-sysfs-proxy@sys-class-gpio.service.d/overlay.conf",
]

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
32 changes: 32 additions & 0 deletions share/gpiod-sysfs-proxy@.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

# Template unit: the instance name is the systemd-escaped mountpoint, e.g.
#
# systemctl enable --now gpiod-sysfs-proxy@run-gpio.service
# systemctl enable --now gpiod-sysfs-proxy@sys-class-gpio.service
#
# Generate the instance name from a path with:
#
# systemd-escape --path /run/gpio
# systemd-escape --path /sys/class/gpio
#
# Inside the unit %I expands back to the unescaped mountpoint path.
#
# Mounting over /sys/class/gpio only works when that directory already exists
# (i.e. the kernel sysfs GPIO interface is enabled). To expose it on a kernel
# where sysfs GPIO is disabled, see the overlay .mount example units shipped
# alongside this file.
Comment thread
obbardc marked this conversation as resolved.

[Unit]
Description=User-space, libgpiod-based GPIO sysfs compatibility layer at %I

[Service]
RuntimeDirectory=gpio
Type=simple
ExecStart=/usr/bin/gpiod-sysfs-proxy %I -f -o allow_other -o default_permissions
ExecStop=/bin/umount %I
Restart=always

[Install]
WantedBy=multi-user.target
14 changes: 14 additions & 0 deletions share/gpiod-sysfs-proxy@sys-class-gpio.service.d/overlay.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

# Instance-specific drop-in: only the sys-class-gpio instance needs the
# /sys/class overlay. Pulling the mounts in here (rather than in the template)
# keeps other instances, e.g. gpiod-sysfs-proxy@run-gpio.service, free of it.
#
# The mount units carry ConditionPathExists=!/sys/class/gpio, so on a kernel
# where the sysfs GPIO interface is enabled they become no-ops and the proxy
# simply mounts over the existing directory.

[Unit]
Requires=run-gpio-sys.mount sys-class.mount
After=run-gpio-sys.mount sys-class.mount
14 changes: 14 additions & 0 deletions share/run-gpio-sys.mount
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

[Unit]
Description=Remount of sysfs for gpiod-sysfs-proxy
PartOf=gpiod-sysfs-proxy@sys-class-gpio.service
ConditionPathExists=!/sys/class/gpio

[Mount]
DirectoryMode=0700
What=sysfs
Where=/run/gpio/sys
Type=sysfs
Options=nosuid,nodev,noexec
17 changes: 17 additions & 0 deletions share/sys-class.mount
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

[Unit]
Description=Overlay on top of /sys/class adding the gpio class directory
Before=gpiod-sysfs-proxy@sys-class-gpio.service
After=run-gpio-sys.mount
PartOf=gpiod-sysfs-proxy@sys-class-gpio.service
ConditionPathExists=!/sys/class/gpio

[Mount]
RuntimeDirectory=gpio/class/gpio
DirectoryMode=0755
What=overlay
Where=/sys/class
Type=overlay
Options=upperdir=/run/gpio/class,lowerdir=/run/gpio/sys/class,workdir=/run/gpio/work,ro,nosuid,nodev,noexec,relatime