mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2025-10-22 23:13:04 +02:00
gpiod-sysfs-proxy: new recipe
Many users are reluctant to use libgpiod instead of the deprecated /sys/class/gpio interface. The gpiod-sysfs-proxy project aims at making the transition easier by implementing a compatibility layer in user-space using FUSE and python3-gpiod. This way we can eat the cookie by disabling the sysfs ABI and have the users have it too by sticking to their existing scripts. The project itself is a very simple setuptools-based python package but the recipe is quite complex due to comprehensive distro integration. By default we use /run/gpio as mountpoint. For full backward compatibility with the kernel interface, the user must explicitly add the 'sys-class-mount' switch to PACKAGECONFIG. We do this because, depending on whether CONFIG_GPIO_SYSFS Kconfig option is enabled, /sys/class/gpio will either be non-empty or not exist at all. In the latter case, we need to somehow create the /sys/class/gpio and, since user-space is not allowed to mkdir() inside sysfs, we use overlayfs for that. As this is rather non-standard, we want the user to be aware of this. We support both systemd and sys V init managers. We also provide a ptest package which uses an external gpio-sysfs-compat-tests script. Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Signed-off-by: Khem Raj <raj.khem@gmail.com>
This commit is contained in:
parent
06eacb769a
commit
ae88d2ff59
|
@ -16,3 +16,7 @@ LAYERVERSION_filesystems-layer = "1"
|
||||||
LAYERDEPENDS_filesystems-layer = "core openembedded-layer networking-layer"
|
LAYERDEPENDS_filesystems-layer = "core openembedded-layer networking-layer"
|
||||||
|
|
||||||
LAYERSERIES_COMPAT_filesystems-layer = "styhead walnascar"
|
LAYERSERIES_COMPAT_filesystems-layer = "styhead walnascar"
|
||||||
|
|
||||||
|
BBFILES_DYNAMIC += " \
|
||||||
|
meta-python:${LAYERDIR}/dynamic-layers/meta-python/recipes-*/*/*.bb \
|
||||||
|
"
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#! /bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: gpiod-sysfs-proxy
|
||||||
|
# Required-Start: $remote_fs $syslog
|
||||||
|
# Required-Stop: $remote_fs $syslog
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 1
|
||||||
|
# Short-Description: User-space, libgpiod-based compatibility layer for linux GPIO sysfs interface.
|
||||||
|
### END INIT INFO
|
||||||
|
#
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Debian init.d script for gpiod-sysfs-proxy
|
||||||
|
# Copyright (c) 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
|
||||||
|
|
||||||
|
# set -e
|
||||||
|
|
||||||
|
# Source function library.
|
||||||
|
. /etc/init.d/functions
|
||||||
|
|
||||||
|
PROG="/usr/bin/gpiod-sysfs-proxy"
|
||||||
|
NAME="gpiod-sysfs-proxy"
|
||||||
|
DESC="/sys/class/gpio compatibility layer"
|
||||||
|
MOUNTPOINT="@mountpoint@"
|
||||||
|
|
||||||
|
test -x $PROG || exit 0
|
||||||
|
|
||||||
|
do_start()
|
||||||
|
{
|
||||||
|
echo -n "Starting $DESC: "
|
||||||
|
|
||||||
|
if [ "$MOUNTPOINT" = "/sys/class/gpio" ] && [ ! -e /sys/class/gpio ]; then
|
||||||
|
mkdir -p /run/gpio/sys /run/gpio/class/gpio /run/gpio/work
|
||||||
|
mount -t sysfs sysfs /run/gpio/sys -o nosuid,nodev,noexec
|
||||||
|
# Bail out if overlayfs is not available
|
||||||
|
set -e
|
||||||
|
mount -t overlay overlay /sys/class \
|
||||||
|
-o upperdir=/run/gpio/class,lowerdir=/run/gpio/sys/class,workdir=/run/gpio/work,nosuid,nodev,noexec,relatime,ro
|
||||||
|
set +e
|
||||||
|
else
|
||||||
|
mkdir -p $MOUNTPOINT
|
||||||
|
fi
|
||||||
|
|
||||||
|
$PROG $MOUNTPOINT -o nonempty -o allow_other -o default_permissions -o entry_timeout=0 -f | logger -i $NAME &
|
||||||
|
echo "done"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_stop()
|
||||||
|
{
|
||||||
|
echo -n "Stopping $DESC: "
|
||||||
|
|
||||||
|
umount $MOUNTPOINT
|
||||||
|
|
||||||
|
mountpoint -q /sys/class
|
||||||
|
if [ "$?" = "0" ]; then
|
||||||
|
umount /sys/class
|
||||||
|
umount /run/gpio/sys
|
||||||
|
rm -rf /run/gpio
|
||||||
|
fi
|
||||||
|
echo "done"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
do_start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
do_stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status $PROG
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
do_stop
|
||||||
|
sleep 1
|
||||||
|
do_start
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: /etc/init.d/$NAME {start|stop|status|restart}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
|
@ -0,0 +1,15 @@
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=User-space, libgpiod-based compatibility layer for linux GPIO sysfs interface
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
RuntimeDirectory=gpio
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/gpiod-sysfs-proxy @mountpoint@ -f -o nonempty -o allow_other -o default_permissions -o entry_timeout=0
|
||||||
|
ExecStop=/bin/umount @mountpoint@
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -0,0 +1,13 @@
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Remount of sysfs for gpiod-sysfs-proxy
|
||||||
|
ConditionPathExists=!/sys/class/gpio
|
||||||
|
|
||||||
|
[Mount]
|
||||||
|
DirectoryMode=0700
|
||||||
|
What=sysfs
|
||||||
|
Where=/run/gpio/sys
|
||||||
|
Type=sysfs
|
||||||
|
Options=nosuid,nodev,noexec
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ptestdir=$(dirname "$(readlink -f "$0")")
|
||||||
|
testbin="gpio-sysfs-compat-tests"
|
||||||
|
|
||||||
|
modprobe gpio-sim
|
||||||
|
modprobe configfs
|
||||||
|
|
||||||
|
mountpoint -q /sys/kernel/config
|
||||||
|
if [ "$?" -ne "0" ]; then
|
||||||
|
mount -t configfs configfs /sys/kernel/config
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $ptestdir/tests
|
||||||
|
|
||||||
|
./$testbin -v --gpio-class @mountpoint@ --chown-user gpio-test > ./$testbin.out 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAIL: $testbin"
|
||||||
|
else
|
||||||
|
echo "PASS: $testbin"
|
||||||
|
fi
|
|
@ -0,0 +1,16 @@
|
||||||
|
# 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.service
|
||||||
|
After=run-gpio-sys.mount
|
||||||
|
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
|
|
@ -0,0 +1,85 @@
|
||||||
|
SUMMARY = "User-space, libgpiod-based compatibility layer for linux GPIO sysfs interface."
|
||||||
|
|
||||||
|
LICENSE = "MIT"
|
||||||
|
LIC_FILES_CHKSUM = "file://COPYING;md5=0dcf8b702b5c96178978c7223f64a73b"
|
||||||
|
|
||||||
|
inherit systemd update-rc.d ptest pypi python_pep517 python_setuptools_build_meta useradd
|
||||||
|
|
||||||
|
PYPI_PACKAGE = "gpiod_sysfs_proxy"
|
||||||
|
|
||||||
|
SRC_URI += " \
|
||||||
|
file://gpiod-sysfs-proxy.service.in \
|
||||||
|
file://run-gpio-sys.mount \
|
||||||
|
file://sys-class.mount \
|
||||||
|
file://gpiod-sysfs-proxy.init.in \
|
||||||
|
file://run-ptest.in \
|
||||||
|
"
|
||||||
|
|
||||||
|
SRC_URI[sha256sum] = "c7830cb6a2c01914df2bc0549aef2dcfcb955520d400f65b3b50fb7a6f77f1b4"
|
||||||
|
|
||||||
|
# For full backward compatibility with the kernel sysfs interface, this option
|
||||||
|
# must be selected. However, we don't make it the default as - with kernel sysfs
|
||||||
|
# disabled - it plays a silly game with /sys/class, where it mounts a read-only
|
||||||
|
# overlay containing the missing /sys/class/gpio directory. This is a rather
|
||||||
|
# non-standard behavior so make sure the user actually wants it.
|
||||||
|
PACKAGECONFIG[sys-class-mount] = ""
|
||||||
|
|
||||||
|
export MOUNTPOINT="${@bb.utils.contains('PACKAGECONFIG', 'sys-class-mount', '\/sys\/class\/gpio', '\/run\/gpio', d)}"
|
||||||
|
|
||||||
|
do_install:append() {
|
||||||
|
if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
|
||||||
|
install -d ${D}${systemd_system_unitdir}
|
||||||
|
install -m 0644 ${UNPACKDIR}/gpiod-sysfs-proxy.service.in ${D}${systemd_system_unitdir}/gpiod-sysfs-proxy.service
|
||||||
|
|
||||||
|
if ${@bb.utils.contains('PACKAGECONFIG', 'sys-class-mount', 'true', 'false', d)}; then
|
||||||
|
install -d ${D}${systemd_system_unitdir}/sysinit.target.wants/
|
||||||
|
|
||||||
|
install -m 0644 ${UNPACKDIR}/run-gpio-sys.mount ${D}${systemd_system_unitdir}/run-gpio-sys.mount
|
||||||
|
install -m 0644 ${UNPACKDIR}/sys-class.mount ${D}${systemd_system_unitdir}/sys-class.mount
|
||||||
|
|
||||||
|
ln -sf ../run-gpio-sys.mount ${D}${systemd_system_unitdir}/sysinit.target.wants/run-gpio-sys.mount
|
||||||
|
ln -sf ../sys-class.mount ${D}${systemd_system_unitdir}/sysinit.target.wants/sys-class.mount
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -i "s/@mountpoint@/$MOUNTPOINT/g" ${D}${systemd_system_unitdir}/gpiod-sysfs-proxy.service
|
||||||
|
elif ${@bb.utils.contains('DISTRO_FEATURES', 'sysvinit', 'true', 'false', d)}; then
|
||||||
|
install -d ${D}${sysconfdir}/init.d
|
||||||
|
install -m 0755 ${UNPACKDIR}/gpiod-sysfs-proxy.init.in ${D}${sysconfdir}/init.d/gpiod-sysfs-proxy
|
||||||
|
sed -i "s/@mountpoint@/$MOUNTPOINT/g" ${D}${sysconfdir}/init.d/gpiod-sysfs-proxy
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSTEMD_SERVICE:${PN} = "gpiod-sysfs-proxy.service"
|
||||||
|
SYSTEMD_AUTO_ENABLE = "enable"
|
||||||
|
|
||||||
|
INITSCRIPT_NAME = "gpiod-sysfs-proxy"
|
||||||
|
INITSCRIPT_PARAMS = "start 20 2 3 4 5 . stop 20 0 1 6 ."
|
||||||
|
|
||||||
|
FILES:${PN} += "/usr/lib/systemd/system"
|
||||||
|
|
||||||
|
RDEPENDS:${PN} += " \
|
||||||
|
python3-fuse \
|
||||||
|
python3-gpiod \
|
||||||
|
python3-pyudev \
|
||||||
|
"
|
||||||
|
|
||||||
|
python __anonymous() {
|
||||||
|
if d.getVar("PTEST_ENABLED") == "1":
|
||||||
|
d.appendVar("SRC_URI", "git://github.com/brgl/gpio-sysfs-compat-tests;protocol=https;branch=main;destsuffix=tests;name=tests")
|
||||||
|
d.setVar("SRCREV_tests", "a3c9daa4650dd1e8d7fd8972db68d9c2c204263d")
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install_ptest() {
|
||||||
|
install -d ${D}${PTEST_PATH}/tests/
|
||||||
|
install -m 0755 ${UNPACKDIR}/run-ptest.in ${D}${PTEST_PATH}/run-ptest
|
||||||
|
sed -i "s/@mountpoint@/$MOUNTPOINT/g" ${D}${PTEST_PATH}/run-ptest
|
||||||
|
install -m 0755 ${UNPACKDIR}/tests/gpio-sysfs-compat-tests ${D}${PTEST_PATH}/tests/gpio-sysfs-compat-tests
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test user is created for verifying chown() and chmod() operations.
|
||||||
|
USERADD_PACKAGES = "${PN}-ptest"
|
||||||
|
GROUPADD_PARAM:${PN}-ptest = "--system gpio-test"
|
||||||
|
USERADD_PARAM:${PN}-ptest = "--system -M -s /bin/nologin -g gpio-test gpio-test"
|
||||||
|
|
||||||
|
RDEPENDS:${PN}-ptest += "kmod"
|
||||||
|
RRECOMMENDS:${PN}-ptest += "kernel-module-gpio-sim kernel-module-configfs"
|
Loading…
Reference in New Issue
Block a user