From 0657f26f70b790095721c690543be2166761cf25 Mon Sep 17 00:00:00 2001 From: jkaczman Date: Mon, 25 May 2026 10:56:16 -0400 Subject: [PATCH 1/2] refactor: swap machine to raspberrypi4-64 for debug image (for now) --- meta-secluso-os/pi-debug-image.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/meta-secluso-os/pi-debug-image.yml b/meta-secluso-os/pi-debug-image.yml index 8a455ab..56db633 100644 --- a/meta-secluso-os/pi-debug-image.yml +++ b/meta-secluso-os/pi-debug-image.yml @@ -21,7 +21,7 @@ signers: gpg_keyserver: keyserver.ubuntu.com # The machine as it is written into the `local.conf` of bitbake. -machine: raspberrypi0-2w-64 +machine: raspberrypi4-64 # The distro name as it is written into the `local.conf` of bitbake. # Selects conf/distro/secluso.conf from meta-secluso-os. distro: secluso @@ -118,7 +118,7 @@ local_conf_header: # meta-raspberrypi sets WKS_FILE with a weak assignment (?=), so we don't need a force override # wks is a custom configuration script used by the wic tool to define the partitioning layout # override theirs with our modified version - WKS_FILE:raspberrypi0-2w-64 = "sdcard-raspberrypi.wks" + WKS_FILE = "sdcard-raspberrypi.wks" # Reference: https://wiki.yoctoproject.org/wiki/Reproducible_Builds # These should be default values. We re-affirm them here to be safe. @@ -159,8 +159,8 @@ local_conf_header: ENABLE_CAMERA = "0" ENABLE_I2C = "1" # Ensure the ov5647 & imx219 overlays are built and deployed to /boot/overlays/ - KERNEL_DEVICETREE:append:raspberrypi0-2w-64 = " overlays/ov5647.dtbo" - KERNEL_DEVICETREE:append:raspberrypi0-2w-64 = " overlays/imx219.dtbo" + KERNEL_DEVICETREE:append = " overlays/ov5647.dtbo" + KERNEL_DEVICETREE:append = " overlays/imx219.dtbo" # Ensure the kernel modules are installed into the image. Needed to properly load in the camera into libcamera # Not all kernel-modules need to be included for proper operation. From 4337db165ab49db6eba194c5ba875f98462dd8c0 Mon Sep 17 00:00:00 2001 From: jkaczman Date: Fri, 29 May 2026 12:08:20 -0400 Subject: [PATCH 2/2] feat(pi): core/ local override; support ICS-43432 mic and IR light re #19 --- meta-secluso-os/pi-debug-image.yml | 18 ++++++- meta-secluso-os/pi-official-image.yml | 9 ++++ .../alsa-state/alsa-state.bbappend | 15 ++++++ .../linux/files/i2s-ics43432-mic-overlay.dts | 51 +++++++++++++++++++ .../linux/linux-raspberrypi_%.bbappend | 20 +++++++- .../recipes-multimedia/alsa/files/asound.conf | 25 +++++++++ .../alsa/secluso-alsa-config_1.0.bb | 16 ++++++ .../secluso-camera-hub-crates.inc | 4 ++ .../secluso-camera-hub_1.0.2.bb | 41 ++++++++++++++- 9 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 meta-secluso-os/recipes-bsp/alsa-state/alsa-state.bbappend create mode 100644 meta-secluso-os/recipes-kernel/linux/files/i2s-ics43432-mic-overlay.dts create mode 100644 meta-secluso-os/recipes-multimedia/alsa/files/asound.conf create mode 100644 meta-secluso-os/recipes-multimedia/alsa/secluso-alsa-config_1.0.bb diff --git a/meta-secluso-os/pi-debug-image.yml b/meta-secluso-os/pi-debug-image.yml index 56db633..3445c78 100644 --- a/meta-secluso-os/pi-debug-image.yml +++ b/meta-secluso-os/pi-debug-image.yml @@ -21,7 +21,7 @@ signers: gpg_keyserver: keyserver.ubuntu.com # The machine as it is written into the `local.conf` of bitbake. -machine: raspberrypi4-64 +machine: raspberrypi0-2w-64 # The distro name as it is written into the `local.conf` of bitbake. # Selects conf/distro/secluso.conf from meta-secluso-os. distro: secluso @@ -30,6 +30,13 @@ distro: secluso # We use 'secluso-image-minimal' to include our own recipes on top of core-image-minimal # Located in recipes-core/images/secluso-pi-image-minimal.bb target: secluso-pi-image-minimal +# Optional local source override for camera hub in debug builds +# This should point at the local core repository root (not camera_hub) +# Example: +# SECLUSO_CAMERA_HUB_USE_LOCAL=1 SECLUSO_CAMERA_HUB_LOCAL_SRC=/home/john/core kas build pi-debug-image.yml +env: + SECLUSO_CAMERA_HUB_USE_LOCAL: null + SECLUSO_CAMERA_HUB_LOCAL_SRC: null repos: # We create a layer for secluso-os. # This allows us to use our own wic/ file. Additionally, we have conf/ if we need it. @@ -166,6 +173,15 @@ local_conf_header: # Not all kernel-modules need to be included for proper operation. # TODO: Remove unnecesary kernel modules IMAGE_INSTALL:append = " kmod i2c-tools kernel-modules" + + # Install ALSA userspace tooling and our own ALSA configuration recipe. + # secluso-alsa-config provides the capture devices used by camera_hub (eg. mic_processed). + IMAGE_INSTALL:append = " alsa-utils alsa-state opus-tools secluso-alsa-config" + # Ensure our I2S microphone overlay is built and put in to /boot/overlays/ + KERNEL_DEVICETREE:append = " overlays/i2s-ics43432-mic.dtbo" + # Enable the Pi I2S controller and load the ICS43432 microphone overlay at boot. + # We additionally enable the PWM overlay for the IR light on GPIO 13. + RPI_EXTRA_CONFIG += "\ndtparam=i2s=on\ndtoverlay=i2s-ics43432-mic\ndtoverlay=pwm,pin=13,func=4\n" # Referenced from https://hub.mender.io/t/how-to-configure-networking-using-systemd-in-yocto-project/1097 # This installs the necessary firmware to connect to WiFi. See LICENSE_FLAGS_ACCEPTED for a relevant discussion. diff --git a/meta-secluso-os/pi-official-image.yml b/meta-secluso-os/pi-official-image.yml index f31e182..cfb894a 100644 --- a/meta-secluso-os/pi-official-image.yml +++ b/meta-secluso-os/pi-official-image.yml @@ -158,6 +158,15 @@ local_conf_header: # Not all kernel-modules need to be included for proper operation. # TODO: Remove unnecesary kernel modules IMAGE_INSTALL:append = " kmod i2c-tools kernel-modules" + + # Install ALSA userspace tooling and our own ALSA configuration recipe. + # secluso-alsa-config provides the capture devices used by camera_hub (eg. mic_processed). + IMAGE_INSTALL:append = " alsa-utils alsa-state opus-tools secluso-alsa-config" + # Ensure our I2S microphone overlay is built and put in to /boot/overlays/ + KERNEL_DEVICETREE:append = " overlays/i2s-ics43432-mic.dtbo" + # Enable the Pi I2S controller and load the ICS43432 microphone overlay at boot. + # We additionally enable the PWM overlay for the IR light on GPIO 13. + RPI_EXTRA_CONFIG += "\ndtparam=i2s=on\ndtoverlay=i2s-ics43432-mic\ndtoverlay=pwm,pin=13,func=4\n" # Referenced from https://hub.mender.io/t/how-to-configure-networking-using-systemd-in-yocto-project/1097 # This installs the necessary firmware to connect to WiFi. See LICENSE_FLAGS_ACCEPTED for a relevant discussion. diff --git a/meta-secluso-os/recipes-bsp/alsa-state/alsa-state.bbappend b/meta-secluso-os/recipes-bsp/alsa-state/alsa-state.bbappend new file mode 100644 index 0000000..32f211f --- /dev/null +++ b/meta-secluso-os/recipes-bsp/alsa-state/alsa-state.bbappend @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 Secluso, Inc. +# Additional terms apply; see the NOTICE file in the repository root. + +do_install:append() { + rm -f ${D}${sysconfdir}/asound.conf + rmdir --ignore-fail-on-non-empty ${D}${sysconfdir} +} + +FILES:${PN}:remove = "${sysconfdir}/asound.conf" +CONFFILES:${PN}:remove = "${sysconfdir}/asound.conf" + +# Make wrapper package installable after removing the stock asound.conf +RDEPENDS:${PN} += "alsa-states" +ALLOW_EMPTY:${PN} = "1" diff --git a/meta-secluso-os/recipes-kernel/linux/files/i2s-ics43432-mic-overlay.dts b/meta-secluso-os/recipes-kernel/linux/files/i2s-ics43432-mic-overlay.dts new file mode 100644 index 0000000..1e1bddd --- /dev/null +++ b/meta-secluso-os/recipes-kernel/linux/files/i2s-ics43432-mic-overlay.dts @@ -0,0 +1,51 @@ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835"; + + fragment@0 { + target-path = "/"; + __overlay__ { + ics43432_codec: ics43432-codec { + #sound-dai-cells = <0>; + compatible = "invensense,ics43432"; + status = "okay"; + }; + }; + }; + + fragment@1 { + target = <&i2s_clk_producer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; + }; + }; + + fragment@2 { + target = <&sound>; + sound_overlay: __overlay__ { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "ICS43432Mic"; + simple-audio-card,bitclock-slave = <&mic_codec>; + simple-audio-card,frame-slave = <&mic_codec>; + status = "okay"; + + simple-audio-card,cpu { + sound-dai = <&i2s_clk_producer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; + + mic_codec: simple-audio-card,codec { + sound-dai = <&ics43432_codec>; + }; + }; + }; + + __overrides__ { + card-name = <&sound_overlay>, "simple-audio-card,name"; + }; +}; diff --git a/meta-secluso-os/recipes-kernel/linux/linux-raspberrypi_%.bbappend b/meta-secluso-os/recipes-kernel/linux/linux-raspberrypi_%.bbappend index 06a03f7..7dfc458 100644 --- a/meta-secluso-os/recipes-kernel/linux/linux-raspberrypi_%.bbappend +++ b/meta-secluso-os/recipes-kernel/linux/linux-raspberrypi_%.bbappend @@ -4,4 +4,22 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files:" -SRC_URI:append = " file://disable-ikconfig.cfg" +SRC_URI:append = " file://disable-ikconfig.cfg file://i2s-ics43432-mic-overlay.dts" + +do_configure:append() { + install -m 0644 ${UNPACKDIR}/i2s-ics43432-mic-overlay.dts \ + ${S}/arch/arm/boot/dts/overlays/i2s-ics43432-mic-overlay.dts + + awk ' + /i2s-ics43432-mic\.dtbo/ { + next + } + /^dtbo-\$\(CONFIG_ARCH_BCM2835\) \+= \\$/ { + print + print " i2s-ics43432-mic.dtbo \\" + next + } + { print } + ' ${S}/arch/arm/boot/dts/overlays/Makefile > ${S}/arch/arm/boot/dts/overlays/Makefile.new + mv ${S}/arch/arm/boot/dts/overlays/Makefile.new ${S}/arch/arm/boot/dts/overlays/Makefile +} diff --git a/meta-secluso-os/recipes-multimedia/alsa/files/asound.conf b/meta-secluso-os/recipes-multimedia/alsa/files/asound.conf new file mode 100644 index 0000000..012ef89 --- /dev/null +++ b/meta-secluso-os/recipes-multimedia/alsa/files/asound.conf @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 Secluso, Inc. +# Additional terms apply; see the NOTICE file in the repository root. + +# Capture the left slot from the ICS-43432 mic and let ALSA plug handle format/rate/channel conversion for mono 16 kHz pipelines. +pcm.mic_mono { + type plug + slave.pcm "hw:ICS43432Mic,0" + ttable.0.0 1 +} + +pcm.mic_processed { + type softvol + slave.pcm "mic_mono" + control { + name "Mic Gain" + card "ICS43432Mic" + } + max_dB 30.0 +} + +ctl.!default { + type hw + card "ICS43432Mic" +} diff --git a/meta-secluso-os/recipes-multimedia/alsa/secluso-alsa-config_1.0.bb b/meta-secluso-os/recipes-multimedia/alsa/secluso-alsa-config_1.0.bb new file mode 100644 index 0000000..aff1b2d --- /dev/null +++ b/meta-secluso-os/recipes-multimedia/alsa/secluso-alsa-config_1.0.bb @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 Secluso, Inc. +# Additional terms apply; see the NOTICE file in the repository root. + +SUMMARY = "ALSA configuration for the ICS-43432 debug mic pipeline" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://asound.conf" + +do_install() { + install -d ${D}${sysconfdir} + install -m 0644 ${UNPACKDIR}/asound.conf ${D}${sysconfdir}/asound.conf +} + +FILES:${PN} = "${sysconfdir}/asound.conf" diff --git a/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub-crates.inc b/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub-crates.inc index d3d69e2..1e055ac 100644 --- a/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub-crates.inc +++ b/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub-crates.inc @@ -167,6 +167,8 @@ SRC_URI += " \ crate://crates.io/ocb3/0.1.0 \ crate://crates.io/once_cell/1.21.4 \ crate://crates.io/opaque-debug/0.3.1 \ + crate://crates.io/opusic-c/1.6.1 \ + crate://crates.io/opusic-sys/0.7.3 \ crate://crates.io/openssl-probe/0.2.1 \ crate://crates.io/p256/0.13.2 \ crate://crates.io/p384/0.13.1 \ @@ -534,6 +536,8 @@ SRC_URI[num-traits-0.2.19.sha256sum] = "071dfc062690e90b734c0b2273ce72ad0ffa95f0 SRC_URI[ocb3-0.1.0.sha256sum] = "c196e0276c471c843dd5777e7543a36a298a4be942a2a688d8111cd43390dedb" SRC_URI[once_cell-1.21.4.sha256sum] = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" SRC_URI[opaque-debug-0.3.1.sha256sum] = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +SRC_URI[opusic-c-1.6.1.sha256sum] = "89f8e9c909466f15e60277212cc4fec082c68a5e1c9f6e373eee716fec2fed47" +SRC_URI[opusic-sys-0.7.3.sha256sum] = "2804e694ef0de3b4cbb254de565053b7cb48d3398df7fd60c6c62bed40c5372a" SRC_URI[openssl-probe-0.2.1.sha256sum] = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" SRC_URI[p256-0.13.2.sha256sum] = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" SRC_URI[p384-0.13.1.sha256sum] = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" diff --git a/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub_1.0.2.bb b/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub_1.0.2.bb index 5cc388c..2274191 100644 --- a/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub_1.0.2.bb +++ b/meta-secluso-os/recipes-secluso-camera-hub/secluso-camera-hub/secluso-camera-hub_1.0.2.bb @@ -6,7 +6,7 @@ # Referenced https://github.com/facebook/openbmc/blob/5bf12b96fd7797c84798049bc404581be8390bc7/meta-facebook/meta-catalina/recipes-catalina/satellite-relay/satellite-relay_0.1.0.bb # Inheriting cargo is what will build the crate here. -inherit cargo cargo-update-recipe-crates systemd +inherit cargo cargo-update-recipe-crates systemd externalsrc SUMMARY = "Recipe to build and install Secluso Camera Hub" HOMEPAGE = "https://github.com/secluo/core" @@ -17,6 +17,9 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=b769fddc23425484f6d001e49426c2ee" SRC_URI = "git://github.com/secluso/core.git;nobranch=1;protocol=https" SRCREV = "7bcbb4e4785fddab7f309b9535b29b98d54136fc" +SECLUSO_CAMERA_HUB_USE_LOCAL ?= "0" +SECLUSO_CAMERA_HUB_LOCAL_SRC ?= "" + # Cargo fingerprints local path crates using their absolute source path # Thus, we copy the workspace to a canonical location before compiling. REPRODUCIBLE_SOURCE_DIR = "/tmp/yocto-reproducible-sources/${BPN}-${PV}-${TARGET_SYS}" @@ -38,6 +41,37 @@ RUSTFLAGS += " --remap-path-prefix=${WORKDIR}=/usr/src/debug/${PN}/${PV}" RUSTFLAGS += " --remap-path-prefix=${S}=/usr/src/debug/${PN}/${PV}/sources" RUSTFLAGS += " --remap-path-prefix=${CARGO_HOME}=cargo_home" +# opusic-sys compiles bundled C sources via a cargo build script. +# Rust path remaps alone are thus not enough to rewrite __FILE__ strings that would embed TMPDIR into the binary. +CFLAGS += " -ffile-prefix-map=${WORKDIR}=/usr/src/debug/${PN}/${PV}" +CFLAGS += " -ffile-prefix-map=${S}=/usr/src/debug/${PN}/${PV}/sources" +CFLAGS += " -ffile-prefix-map=${CARGO_HOME}=cargo_home" + +python __anonymous() { + import os + + if d.getVar("SECLUSO_CAMERA_HUB_USE_LOCAL") != "1": + d.setVar("S", d.getVar("REPRODUCIBLE_SOURCE_DIR")) + return + + local_src = d.getVar("SECLUSO_CAMERA_HUB_LOCAL_SRC") + if not local_src: + bb.fatal("SECLUSO_CAMERA_HUB_USE_LOCAL=1 requires SECLUSO_CAMERA_HUB_LOCAL_SRC to be set to the local core repository root") + if not os.path.isdir(local_src): + bb.fatal("SECLUSO_CAMERA_HUB_LOCAL_SRC does not exist or is not a directory: %s" % local_src) + + # externalsrc points the recipe directly at the user's local core checkout. + # This is only intended for debug image workflows where we want to iterate without doing git commits across machines + d.setVar("EXTERNALSRC", local_src) + d.setVar("EXTERNALSRC_BUILD", os.path.join(d.getVar("WORKDIR"), "externalsrc-build")) + d.setVar("S", local_src) + # BitBake does not automatically notice arbitrary source edits (stale cache) + # Thus, in local debug mode, we rebuild the packaging pipeline every time we run + for task in ("do_compile", "do_install", "do_package", "do_packagedata", + "do_package_qa", "do_package_write_rpm"): + d.setVarFlag(task, "nostamp", "1") +} + # https://wiki.koansoftware.com/index.php/Add_a_systemd_service_file_into_a_Yocto_image SYSTEMD_AUTO_ENABLE = "enable" SYSTEMD_SERVICE:${PN} = "secluso_camera_hub.service" @@ -49,6 +83,11 @@ python do_unpack:append() { import os import shutil + # When externalsrc is enabled, the source tree is already the caller's local checkout. + # Thus, we skip the reproducible copy step that is only needed for the pinned git for releases for reproducibility + if d.getVar("SECLUSO_CAMERA_HUB_USE_LOCAL") == "1": + return + source_dir = os.path.join(d.getVar("WORKDIR"), "sources", f"{d.getVar('BPN')}-{d.getVar('PV')}") reproducible_source_dir = d.getVar("S")