From 45025b31bfcc24b465a448281e2b1d72a6a836d2 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 2 Sep 2026 15:40:13 +0700 Subject: [PATCH 1/2] New package: samsung-camera-relay --- .../files/default/samsung-camera-relay | 1 + .../files/libcamera/ipa/simple/ov02c10.yaml | 15 +++ .../files/modules-load/v4l2loopback.conf | 1 + .../files/udev/74-camera-relay-mc-nodes.rules | 12 ++ .../wireplumber/50-disable-ipu6-v4l2.conf | 13 ++ .../52-disable-libcamera-node.conf | 13 ++ .../files/xdg/samsung-camera-relay.desktop | 6 + .../patches/systemd-to-runit.patch | 122 ++++++++++++++++++ srcpkgs/samsung-camera-relay/template | 60 +++++++++ 9 files changed, 243 insertions(+) create mode 100644 srcpkgs/samsung-camera-relay/files/default/samsung-camera-relay create mode 100644 srcpkgs/samsung-camera-relay/files/libcamera/ipa/simple/ov02c10.yaml create mode 100644 srcpkgs/samsung-camera-relay/files/modules-load/v4l2loopback.conf create mode 100644 srcpkgs/samsung-camera-relay/files/udev/74-camera-relay-mc-nodes.rules create mode 100644 srcpkgs/samsung-camera-relay/files/wireplumber/50-disable-ipu6-v4l2.conf create mode 100644 srcpkgs/samsung-camera-relay/files/wireplumber/52-disable-libcamera-node.conf create mode 100644 srcpkgs/samsung-camera-relay/files/xdg/samsung-camera-relay.desktop create mode 100644 srcpkgs/samsung-camera-relay/patches/systemd-to-runit.patch create mode 100644 srcpkgs/samsung-camera-relay/template diff --git a/srcpkgs/samsung-camera-relay/files/default/samsung-camera-relay b/srcpkgs/samsung-camera-relay/files/default/samsung-camera-relay new file mode 100644 index 00000000000000..edc31a38bd7664 --- /dev/null +++ b/srcpkgs/samsung-camera-relay/files/default/samsung-camera-relay @@ -0,0 +1 @@ +RELAY_COLOR_FILTER="videoflip method=rotate-180" diff --git a/srcpkgs/samsung-camera-relay/files/libcamera/ipa/simple/ov02c10.yaml b/srcpkgs/samsung-camera-relay/files/libcamera/ipa/simple/ov02c10.yaml new file mode 100644 index 00000000000000..650684a0a7ff2d --- /dev/null +++ b/srcpkgs/samsung-camera-relay/files/libcamera/ipa/simple/ov02c10.yaml @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: CC0-1.0 +%YAML 1.1 +--- +version: 1 +algorithms: + - BlackLevel: + - Awb: + - Ccm: + ccms: + - ct: 6500 + ccm: [ 1, 0, 0, + 0, 0.7, 0, + 0, 0, 1] + - Lut: + - Agc: diff --git a/srcpkgs/samsung-camera-relay/files/modules-load/v4l2loopback.conf b/srcpkgs/samsung-camera-relay/files/modules-load/v4l2loopback.conf new file mode 100644 index 00000000000000..d394e47bc8194b --- /dev/null +++ b/srcpkgs/samsung-camera-relay/files/modules-load/v4l2loopback.conf @@ -0,0 +1 @@ +v4l2loopback diff --git a/srcpkgs/samsung-camera-relay/files/udev/74-camera-relay-mc-nodes.rules b/srcpkgs/samsung-camera-relay/files/udev/74-camera-relay-mc-nodes.rules new file mode 100644 index 00000000000000..c9733352465c30 --- /dev/null +++ b/srcpkgs/samsung-camera-relay/files/udev/74-camera-relay-mc-nodes.rules @@ -0,0 +1,12 @@ +# Tag media controller video nodes for the samsung-camera-relay group. +ACTION=="remove", GOTO="camera_relay_mc_end" +SUBSYSTEM!="video4linux", GOTO="camera_relay_mc_end" + +KERNEL=="video*", ENV{ID_V4L_IO_MC}=="", \ + IMPORT{program}="/usr/lib/udev/camera-relay-v4l2-io-mc $devnode" + +ENV{ID_V4L_IO_MC}=="1", GROUP="samsung-camera-relay", MODE="0660", TAG-="uaccess", \ + ENV{ID_V4L_CAPABILITIES}="", ENV{ID_V4L_PRODUCT}="", \ + RUN+="/usr/bin/setfacl -b $devnode" + +LABEL="camera_relay_mc_end" diff --git a/srcpkgs/samsung-camera-relay/files/wireplumber/50-disable-ipu6-v4l2.conf b/srcpkgs/samsung-camera-relay/files/wireplumber/50-disable-ipu6-v4l2.conf new file mode 100644 index 00000000000000..201fd7eff589eb --- /dev/null +++ b/srcpkgs/samsung-camera-relay/files/wireplumber/50-disable-ipu6-v4l2.conf @@ -0,0 +1,13 @@ +# Hide IPU6 raw video nodes. Apps use the v4l2 relay instead. +monitor.v4l2.rules = [ + { + matches = [ + { device.name = "~v4l2_device.pci-0000_00_05*" } + ] + actions = { + update-props = { + device.disabled = true + } + } + } +] diff --git a/srcpkgs/samsung-camera-relay/files/wireplumber/52-disable-libcamera-node.conf b/srcpkgs/samsung-camera-relay/files/wireplumber/52-disable-libcamera-node.conf new file mode 100644 index 00000000000000..fb5e00f928575a --- /dev/null +++ b/srcpkgs/samsung-camera-relay/files/wireplumber/52-disable-libcamera-node.conf @@ -0,0 +1,13 @@ +# Hide the direct libcamera node. It shows black, apps use the relay instead. +monitor.libcamera.rules = [ + { + matches = [ + { device.name = "~libcamera_device.*" } + ] + actions = { + update-props = { + device.disabled = true + } + } + } +] diff --git a/srcpkgs/samsung-camera-relay/files/xdg/samsung-camera-relay.desktop b/srcpkgs/samsung-camera-relay/files/xdg/samsung-camera-relay.desktop new file mode 100644 index 00000000000000..b1156c8d800359 --- /dev/null +++ b/srcpkgs/samsung-camera-relay/files/xdg/samsung-camera-relay.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Application +Name=Samsung Camera Relay +Comment=On-demand libcamera to v4l2loopback relay for Samsung Galaxy Book +Exec=/usr/bin/camera-relay start --on-demand +X-GNOME-Autostart-enabled=true diff --git a/srcpkgs/samsung-camera-relay/patches/systemd-to-runit.patch b/srcpkgs/samsung-camera-relay/patches/systemd-to-runit.patch new file mode 100644 index 00000000000000..2cebb957f975aa --- /dev/null +++ b/srcpkgs/samsung-camera-relay/patches/systemd-to-runit.patch @@ -0,0 +1,122 @@ +--- a/camera-relay/camera-relay 2026-09-02 01:16:39.637718957 +0700 ++++ b/camera-relay/camera-relay 2026-09-02 01:16:44.231689928 +0700 +@@ -14,6 +14,8 @@ + + set -euo pipefail + ++[[ -r /etc/default/samsung-camera-relay ]] && . /etc/default/samsung-camera-relay ++ + CARD_LABEL="Camera Relay" + PID_FILE="${XDG_RUNTIME_DIR:-/tmp}/camera-relay.pid" + CACHE_DIR="${XDG_RUNTIME_DIR:-/tmp}" +@@ -22,9 +24,9 @@ + STATE_CACHE="${CACHE_DIR}/camera-relay-state" + SERVICE_DIR="${HOME}/.config/systemd/user" + SERVICE_NAME="camera-relay.service" +-LOOPBACK_CONF="/etc/modprobe.d/99-camera-relay-loopback.conf" +-MONITOR_BIN="/usr/local/bin/camera-relay-monitor" +-LAUNCHER_BIN="/usr/local/bin/camera-relay-gst" ++LOOPBACK_CONF="/usr/lib/modprobe.d/99-camera-relay-loopback.conf" ++MONITOR_BIN="/usr/bin/camera-relay-monitor" ++LAUNCHER_BIN="/usr/bin/camera-relay-gst" + + # Arguments shared by every launcher invocation. The launcher is setgid, so it + # replaces its environment wholesale rather than trusting what it inherited — +@@ -94,8 +96,8 @@ + local -a cam_cmd=() + if [[ -x "$LAUNCHER_BIN" ]] && "$LAUNCHER_BIN" --list-cameras &>/dev/null; then + cam_cmd=("$LAUNCHER_BIN" --list-cameras) +- elif [[ -x /usr/local/bin/cam ]] && /usr/local/bin/cam -l &>/dev/null; then +- cam_cmd=(/usr/local/bin/cam -l) ++ elif [[ -x /usr/bin/cam ]] && /usr/bin/cam -l &>/dev/null; then ++ cam_cmd=(/usr/bin/cam -l) + elif command -v cam &>/dev/null; then + cam_cmd=(cam -l) + fi +@@ -223,7 +225,7 @@ + + if ! detect_loopback_device &>/dev/null; then + die "v4l2loopback loaded but no loopback device found. +-Check /etc/modprobe.d/ for v4l2loopback configuration." ++Check /usr/lib/modprobe.d/ for v4l2loopback configuration." + fi + } + +@@ -241,7 +243,7 @@ + } + + is_persistent() { +- systemctl --user is-enabled "$SERVICE_NAME" &>/dev/null 2>&1 ++ return 1 + } + + # Both relay modes keep the loopback open for as long as they run: the always-on +@@ -729,7 +731,6 @@ + + nudge_wireplumber() { + local dev="$1" +- command -v systemctl &>/dev/null || return 0 + command -v pw-cli &>/dev/null || return 0 + + local real node advertised +@@ -767,10 +768,8 @@ + fi + + info "WirePlumber has stale formats for $dev (sees ${advertised:-none}, device offers $want)" +- info "Restarting WirePlumber so PipeWire-based apps (Chrome, Brave) see a usable camera" +- # --no-block: this unit is ordered After=wireplumber.service, so waiting on +- # a wireplumber job from inside our own ExecStartPost can deadlock. +- systemctl --user restart --no-block wireplumber 2>/dev/null || true ++ info "Killing WirePlumber — PipeWire will respawn it with correct formats" ++ pkill -x wireplumber 2>/dev/null || true + } + + cmd_nudge_wireplumber() { +@@ -1225,7 +1224,7 @@ + # first is not a curiosity — it is the bug. + local want_pin="" unit_pin="" env_pin="${__EGL_VENDOR_LIBRARY_FILENAMES:-}" + want_pin=$(detect_egl_vendor_pin) || want_pin="" +- if systemctl --user cat "$SERVICE_NAME" &>/dev/null; then ++ if false; then + unit_pin=$(systemctl --user cat "$SERVICE_NAME" 2>/dev/null \ + | grep -oP '^Environment=__EGL_VENDOR_LIBRARY_FILENAMES=\K.*' | tail -1) || unit_pin="" + fi +@@ -1245,12 +1244,11 @@ + # manager, and this service inherits it — so a pin can be present and inert. + # Report all three layers, because only the effective one is the answer. + local unit_mode="" inherited_mode="" mode_file="" mf effective_mode +- if systemctl --user cat "$SERVICE_NAME" &>/dev/null; then ++ if false; then + unit_mode=$(systemctl --user cat "$SERVICE_NAME" 2>/dev/null \ + | grep -oP '^Environment=LIBCAMERA_SOFTISP_MODE=\K.*' | tail -1) || unit_mode="" + fi +- inherited_mode=$(systemctl --user show-environment 2>/dev/null \ +- | grep -oP '^LIBCAMERA_SOFTISP_MODE=\K.*' | tail -1) || inherited_mode="" ++ inherited_mode="${LIBCAMERA_SOFTISP_MODE:-}" + [[ -z "$inherited_mode" ]] && inherited_mode="${LIBCAMERA_SOFTISP_MODE:-}" + for mf in /etc/environment.d/*.conf "$HOME/.config/environment.d"/*.conf; do + [[ -f "$mf" ]] || continue +@@ -1364,12 +1362,12 @@ + else + echo " monitor binary: MISSING ($MONITOR_BIN) — on-demand mode cannot start" + fi +- if systemctl --user cat "$SERVICE_NAME" &>/dev/null; then ++ if false; then + # is-enabled/is-active print their answer AND exit non-zero when the + # answer is negative, so `|| echo ...` would print it a second time. + echo " service: $(systemctl --user is-enabled "$SERVICE_NAME" 2>/dev/null || true)/$(systemctl --user is-active "$SERVICE_NAME" 2>/dev/null || true)" + else +- echo " service: not installed" ++ echo " service: managed by xdg-autostart" + fi + + # The decisive check. Everything above can look healthy while the loopback +@@ -1664,7 +1662,7 @@ + echo " $lf: empty or missing" + fi + done +- if systemctl --user cat "$SERVICE_NAME" &>/dev/null; then ++ if false; then + echo " systemctl --user status $SERVICE_NAME:" + { systemctl --user status "$SERVICE_NAME" --no-pager -n 15 2>&1 | sed 's/^/ /'; } || true + fi diff --git a/srcpkgs/samsung-camera-relay/template b/srcpkgs/samsung-camera-relay/template new file mode 100644 index 00000000000000..38a85c4c3de34f --- /dev/null +++ b/srcpkgs/samsung-camera-relay/template @@ -0,0 +1,60 @@ +# Template file for 'samsung-camera-relay' + +pkgname=samsung-camera-relay +version=0.3.68 +revision=1 +short_desc="On-demand libcamera to v4l2loopback relay for Samsung Galaxy Book" +maintainer="Louis " +license="GPL-2.0-only" +homepage="https://github.com/Andycodeman/samsung-galaxy-book-linux-fixes" +changelog="https://github.com/Andycodeman/samsung-galaxy-book-linux-fixes/releases" +distfiles="https://github.com/Andycodeman/samsung-galaxy-book-linux-fixes/archive/refs/tags/v${version}.tar.gz" +checksum="817f0137f6ce32b72845d592168c63a7ef2f6638aa9d233eb3c9b76006c6adb9" +depends="gstreamer1 gst-plugins-base1 libcamera pipewire v4l2loopback v4l-utils python3" +system_groups="samsung-camera-relay" +archs="x86_64" + +do_build() { + mkdir -p build + + # camera-relay-gst drops privileges via setgid before touching /dev/video* + cc -O2 -Wall -o build/camera-relay-gst \ + "${wrksrc}/camera-relay/camera-relay-gst.c" + + # camera-relay-monitor idles with black frames until an app opens the device + cc -O2 -Wall -o build/camera-relay-monitor \ + "${wrksrc}/camera-relay/camera-relay-monitor.c" + + # v4l2-io-mc is imported by the udev rule to tag MC nodes + cc -O2 -Wall -o build/camera-relay-v4l2-io-mc \ + "${wrksrc}/camera-relay/v4l2-io-mc.c" +} + +do_install() { + vbin build/camera-relay-gst + vbin build/camera-relay-monitor + vinstall build/camera-relay-v4l2-io-mc 755 usr/lib/udev + + vbin "${wrksrc}/camera-relay/camera-relay" + vbin "${wrksrc}/camera-relay/chromium-pipewire-camera.sh" chromium-pipewire-camera + vinstall "${wrksrc}/camera-relay/99-camera-relay-loopback.conf" 644 usr/lib/modprobe.d + vinstall "${FILESDIR}/udev/74-camera-relay-mc-nodes.rules" 644 usr/lib/udev/rules.d + + # WirePlumber rules: disable the broken direct libcamera node and raw IPU6 V4L2 + # nodes so apps use the v4l2 relay instead (WP 0.5+ conf-d format) + vmkdir etc/wireplumber/wireplumber.conf.d + vinstall "${FILESDIR}/wireplumber/50-disable-ipu6-v4l2.conf" 644 etc/wireplumber/wireplumber.conf.d + vinstall "${FILESDIR}/wireplumber/52-disable-libcamera-node.conf" 644 etc/wireplumber/wireplumber.conf.d + + vmkdir etc/default + vinstall "${FILESDIR}/default/samsung-camera-relay" 644 etc/default samsung-camera-relay + + vmkdir usr/lib/modules-load.d + vinstall "${FILESDIR}/modules-load/v4l2loopback.conf" 644 usr/lib/modules-load.d + + vmkdir etc/xdg/autostart + vinstall "${FILESDIR}/xdg/samsung-camera-relay.desktop" 644 etc/xdg/autostart + + vmkdir usr/share/libcamera/ipa/simple + vinstall "${FILESDIR}/libcamera/ipa/simple/ov02c10.yaml" 644 usr/share/libcamera/ipa/simple +} From 72b72d3122b4c0e620ebbafb6f6940686abe6976 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 2 Sep 2026 15:40:13 +0700 Subject: [PATCH 2/2] New package: samsung-ov02c10-clockfix --- srcpkgs/samsung-ov02c10-clockfix/template | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 srcpkgs/samsung-ov02c10-clockfix/template diff --git a/srcpkgs/samsung-ov02c10-clockfix/template b/srcpkgs/samsung-ov02c10-clockfix/template new file mode 100644 index 00000000000000..8cd68ab584ba7f --- /dev/null +++ b/srcpkgs/samsung-ov02c10-clockfix/template @@ -0,0 +1,28 @@ +# Template file for 'samsung-ov02c10-clockfix' + +pkgname=samsung-ov02c10-clockfix +version=0.3.68 +revision=1 +short_desc="OV02C10 26MHz clock fix for Samsung Galaxy Book" +maintainer="Louis " +license="GPL-2.0-only" +homepage="https://github.com/Andycodeman/samsung-galaxy-book-linux-fixes" +changelog="https://github.com/Andycodeman/samsung-galaxy-book-linux-fixes/releases" +distfiles="https://github.com/Andycodeman/samsung-galaxy-book-linux-fixes/archive/refs/tags/v${version}.tar.gz" +checksum="817f0137f6ce32b72845d592168c63a7ef2f6638aa9d233eb3c9b76006c6adb9" +depends="dkms xbps-triggers>=0.121_1" +dkms_modules="samsung-ov02c10-clockfix ${version}" +triggers="dkms" +archs="x86_64" + +post_extract() { + sed -i \ + -e 's/^PACKAGE_NAME=.*/PACKAGE_NAME="samsung-ov02c10-clockfix"/' \ + -e 's/^PACKAGE_VERSION=.*/PACKAGE_VERSION="'"${version}"'"/' \ + ov02c10-26mhz-fix/dkms.conf +} + +do_install() { + vmkdir usr/src/samsung-ov02c10-clockfix-${version} + vcopy ov02c10-26mhz-fix/* usr/src/samsung-ov02c10-clockfix-${version} +}