Changes in this release:
- 69fd433 soc/ingenic: state a family's shared values once (#1451) The family files enumerated one ifeq block per model, so a value the whole family shares got repeated once per model. t33 named isvp_t33_sfcnor eight times; a1 and t21 named theirs five times each; t10 repeated its RAM size three times. State what the models share once, and express what differs as an exhaustive if/else: # what's common SOC_ARCH := xburst1 SOC_FAMILY := t33 SOC_UBOOT_NOR := isvp_t33_sfcnor # what's different ifneq ($(filter $(SOC_MODEL),t33n t33vn t33zn),) SOC_RAM_MB := 128 else SOC_RAM_MB := 64 endif No variable is assigned a value that a later line replaces. A default with per-model overrides would read shorter still, but it means every model briefly holds a value that is wrong for it, and a model added to the filter and nowhere else would inherit that default rather than being noticed. Which value is common differs by family. t10 shares a RAM size and splits on the bootloader; a1 and t21 share a bootloader and split on RAM; t20, t40 and t41 vary in both, so their branches carry both lines. t41 gains least -- its six parts take six different NAND defconfigs -- but a per-model ladder still reads shorter than six ifeq blocks. Changed: a1, t10, t20, t21, t33, t40, t41 -- 153 lines out, 63 in. Left alone: c100 has one model. t23, t30, t31 and t32 have a distinct bootloader per model with no majority to hoist, so this would save a line or two while making a model's values harder to find. t31's eight models carry five NOR defconfigs and six NAND ones -- that table is earning its length. No functional change, verified two ways: 1. Evaluated both versions for all 35 models the seven filters claim and diffed every variable they set (SOC_FAMILY, SOC_ARCH, SOC_RAM_MB, SOC_UBOOT_NOR, SOC_UBOOT_NAND, SOC_UBOOT_BIN). Identical. 2. Checked that no file assigns a variable at both the common level and inside a branch. Worth doing properly because 27 of the 54 models have no camera config -- including all eight t33 parts -- so no build would have caught a wrong value. Co-authored-by: John Chia john@johnchia.com Co-authored-by: Paul Philippov themactep@gmail.com
- 97f207c raptor family: bump to current heads raptor 712d513: set-fps now reaches the SDP of the next client (rvd republishes the ring header, rsd refreshes its rate cache), and audio clock resync bursts are summarised per episode instead of warning once per threshold crossing, so a sustained loss no longer evicts the syslog ring. Both contributed by johnchia. raptor-hal ec778b3: hal_gpio_set configures the direction on pins it exported itself (fresh sysfs exports are inputs, value writes were failing EPERM on images where init scripts configure nothing). Also johnchia. raptor-ipc and raptor-common move for the new diff-scoped clang-format CI only; no code change. compy stays at c12c594, which the raptor head still requires for the SR clock reference API. Combination build-verified for T41 from these exact heads.
- f0851c3 raptor, compy: bump to current heads together rsd now anchors audio RTCP sender reports on compy's new media-clock reference API, so raptor c59041c does not build against the old compy. compy c12c594: sender reports project NTP and RTP from one sampled instant and applications supply the (rtp timestamp, monotonic instant) reference defining the media clock (RFC 3550 6.4.1). raptor c59041c: the audio timeline campaign from the T23 field report (rtcp_sr blips every 5s). AAC frames stamped on the sample grid instead of the 20ms chunk grid (the weave was baked into recordings), rad's synthetic clock and rsd's wire steering both slewed proportionally instead of deadband stepping, an audio SDP header use-after-free fixed, and sender reports anchored on capture time. Measured on T31: steady sender-report mapping wobble fell from 16..46ms per 5s to under 4ms on every codec; 48k HE-AAC on T41 reads 0.6ms. rtcp_sr can stay enabled everywhere.
- b2d225d prudynt-t: fix dead version pin, bump to 6afc440 d5336b3d no longer resolves in themactep/prudynt-t (422 No commit found). Bump to the current stable head, which also carries the RTSP audio-only session fix from themactep/prudynt-t#30. Signed-off-by: Paul Philippov paul@themactep.com
- 32d442e raptor, raptor-hal: bump to current heads raptor dd05912104451e4bebbbf239e636905c8537980a: the T41 refmode keyframe drop fix (silent publish_ref rejection starved every new RTSP client once the encoder used a third buffer), rmr segment rotation aligned to the wall boundary (the pre-boundary IDR request landed a full GOP late on long-GOP HEVC), the day/night campaign for Gen1 sensors (IR-off ambient probe, EV dip, photo trigger dark boot in seconds, forced modes always drive hardware), the rsd send queue extracted and unit-tested, and a ric audit pass (config file clamped like the ctrl API, SIGFPE on poll_interval_ms=0 fixed, ctrl surface validates and rejects unknown commands). raptor-hal d473d8a85f026a0c493fdcee02b7952730cc6d8f: real AE histogram luma and exposure-time fallback on Gen1 SoCs, the foundation for the day/night work.
- 857eea6 configs: fix leakage
- 3e538ec open-isp: integrate the complete open media stack (#1368) * open-isp: integrate the complete open media stack Extend open-tx-isp to its current T23, T31, T40, and T41 targets, with OpenIMP on its supported T31 and T40 platforms. Pin open-tx-isp after its native canonical-module and T40 SDK sensor-registry integration. Add an opt-in aggregate profile that selects the neo system and audio libraries, while making the proprietary providers mutually exclusive. Order the replacement libraries before streamer consumers and preserve them during target finalization. Document the current support matrix and limitations. Camera profiles remain unchanged; local fragments can opt individual builds into the complete open stack. Signed-off-by: Matt Davis matteius@gmail.com * PR feedback * open-isp: add provider choice and update open stack Signed-off-by: Matt Davis matteius@gmail.com * raptor: gate V4L2 OpenIMP backend with provider Signed-off-by: Matt Davis matteius@gmail.com * open-isp: advance source pins for mainline T31 fixes Signed-off-by: Matt Davis matteius@gmail.com * openimp: make symbol coverage locale-stable Signed-off-by: Matt Davis matteius@gmail.com --------- Signed-off-by: Matt Davis matteius@gmail.com
- 19ac212 raptor: let daynightd replace RIC as the day/night engine Invert the exclusion from 5c29bf3: daynightd is selectable on any image again, and selecting it disables RIC instead (both would drive the same IR-CUT and LED pins and ship the same wrapper scripts). The raptor wrappers install only with RIC, so daynightd images get its scripts; json-imp.cgi prefers daynightd when present, so the web UI drives whichever engine the image ships.
- 5c29bf3 daynightd: exclude on raptor images Raptor's ric owns day/night and the same wrapper script names, so daynightd on a raptor image means two daemons driving the same GPIO pins plus a rootfs file collision. Prudynt still selects daynightd; the streamer choice already keeps raptor out of those configs.
- 579c94e raptor: daynight, ircut and light wrappers for the web UI On raptor images the daynightd package is absent, so the web UI's day/night, ircut and light calls went nowhere. These wrappers keep the daynightd era CLI and route it through raptorctl: ric owns the filter, the IR LEDs and the ISP mode, so read/toggle answer from live ric state instead of a run file, auto is a real verb, and ir850/ir940 switching stays coherent with automatic day/night. White light keeps the stock gpio path with active_low handling. json-imp.cgi branches per streamer: raptor paths skip the daynightd config keys and reload, prudynt paths are unchanged. Validated on z55 T31: full verb matrix, filter+LED+ISP coherent on mode changes, gpio readback confirms LED level, camera left in auto. Supersedes the approach in PR #1454.
- fcc0521 thingino-pkg: use curl instead of wget wget is not present in the firmware image. curl is provided by thingino-libcurl, so add it as a dependency and switch the download command. Co-authored-by: Matias De lellis matiasdelellis@users.noreply.github.com
- 90214d0 webui: report a failed termbin upload instead of an empty redirect On failure url is empty, and unquoted it left redirect_to with no arguments at all, so the response was a 303 carrying an empty Location: a broken redirect and no explanation. The path was barely reachable while the old bin accepted anything; the bin refuses payloads, oversized bodies and an exhausted daily allowance, so it is reachable now. Uses the flash message every other failure in this file already uses.
- 2c43257 send2termbin: post to the diagnostics bin over HTTPS The bin is a Cloudflare Worker now, not fiche on a raw TCP port, so netcat cannot reach it. stdout stays one line so url=$(send2termbin) keeps working for thingino-diag -u, -j and the web UI. Also stops the empty-file branch printing stray echo args and leaking its temp file. thingino-diag and the web UI both said uploads are kept for a week and named the old host. The bin keeps diagnostic reports for three days, and the hostname now lives only in send2termbin.
- f5113c8 scripts/tts: add standardized Kokoro TTS pipeline Add text-to-speech audio generation using Kokoro-82M neural TTS model with pinned voice configuration for repeatable output across sessions. - setup.sh: one-time bootstrap (downloads model + voices, creates venv) - generate.py: main engine (text -> espeak-ng phonemes -> Kokoro -> WAV) - config.yaml: locked voice (af_heart), speed, format settings - run.sh / batch.sh: convenience wrappers (single phrase or batch) - kokoro/: spacy-free model modules (avoids Python 3.14 incompatibility) - README.md: full documentation Model weights and voices are downloaded by setup.sh and gitignored. Signed-off-by: Paul Philippov paul@themactep.com
- fbcd67f webui: merge motion and speaker save buttons into one The "Play audio on speaker" checkbox was saved only by the "Save Motion Settings" button (as motion.playonspeaker to /etc/prudynt.json) while the speaker file/volume/gain/loop were saved separately by "Save Speaker Settings" (to /etc/send2.json). Since the checkbox is visually grouped with the speaker controls, users naturally clicked the wrong button and the setting was lost on reload. Merge both save functions into a single "Save Settings" button that sends motion and speaker in one request. Update the backend CGI to handle combined payloads by extracting each domain's key to isolated temp files before import, and change the speaker branch from elif to a separate if so both domains are processed. Signed-off-by: Paul Philippov paul@themactep.com
- 7b4dbb2 webui: redesign play on speaker in motion detection form
- 04ac518 thingino-raptor: update config builder
- 515785e thingino-raptor: bump pin for timelapse capture and the PSI cadence fix raptor 7abaeb7a: rmr gains timelapse mode -- keyframes sampled at an interval into an ordinary all-intra MP4 (playback compresses real time by interval x playback_fps), stored under its own quota, carrying the same SEI timecodes and Ed25519 signature chain as every recording; controlled via raptorctl timelapse-* and the [timelapse] config section, disabled by default. rsr also emits PSI a frame early so the DVB 500ms table cadence holds on the wire at any frame rate.
- 675fe7a timps: bump TIMPS_VERSION to v1.8.4 Self-heals ISP hflip/vflip/running_mode reverting mid-run on a framesource chn0 idle->active cycle, with no reboot or config change involved. See Lu-Fi/timps@v1.8.4 for details.
- c219ea6 webui: add speaker config and playonspeaker toggle to Send to Services page Add Speaker configuration card to the Send to Services page with fields for file path, volume, gain, and loop count. Add 'Play audio on speaker when motion detected' toggle to the Motion Detection card. Wire both through json-send2.cgi (GET/POST) and send.cgi (test button). Signed-off-by: WLTB-Gino WLTB-Gino@users.noreply.github.com
- 33597f2 prudynt-t: add missing playonspeaker script The motion script calls 'playonspeaker &' when motion.playonspeaker is enabled, but no such script was ever installed. This left the speaker notification feature completely non-functional. Add a playonspeaker script that reads speaker config (file, volume, gain, loop) from /etc/send2.json and invokes the existing 'play' command, matching the pattern of the other send2* scripts. Signed-off-by: WLTB-Gino gino@wltechblog.com
- ad87587 Update buildroot to latest version
- 9ee8274 configs: add thingino.json and prudynt.json for Wyze Cam Pan v1 JXF23
- 0dac2ae configs: add Wyze Cam Pan v1 (T20X, JXF23, RTL8189FTV) Newer hardware revisions of the Wyze Cam Pan v1 ship with a JXF23 sensor and RTL8189FTV WiFi chip instead of the original JXF22 and RTL8189ETV. The board layout, GPIOs, and motors are identical. Detected via UART: - sinfo: Successful sensor detection: jxf23 - SDIO Vendor: 0x024c, Device: 0xf179 (RTL8189FTV) Based on wyze_campan1_t20x_jxf22_rtl8189etv with sensor changed from jxf22 to jxf23 and WiFi from RTL8189ES to RTL8189FS. Reported-by: Discord user (Pan V1 owner) Signed-off-by: WLTB-Gino wltb.gino@gmail.com
- 358df9b overrides: use BR2_EXTERNAL_THINGINO_PATH for package paths THINGINO_EXTERNAL_PATH is defined only in thingino-overrides.mk, which is loaded via BR2_PACKAGE_OVERRIDE_FILE and therefore only in camera builds (core.fragment). But external.mk glob-includes every package//.mk in every build, so in toolchain builds the variable expands empty and paths degrade to /package/...: wireguard-tools then fails "install: cannot stat" since 4fd3e36, and its hash file has been silently skipped all along (buildroot treats a missing hash file as a warning). Use BR2_EXTERNAL_THINGINO_PATH like every other package .mk file; it is defined and unquoted by the time recipes and hooks expand.
- a36d3fa thingino-vpn: move the WireGuard default back to the config layer 70c79b9 abstracted the VPN choice into package/thingino-vpn but flipped its default from NONE to WIREGUARD and dropped the BR2_THINGINO_VPN_WIREGUARD=y policy line from the fragments. A Kconfig choice always resolves to one option, so from that point every config that did not opt out - including all 27 toolchain defconfigs - silently built wireguard-tools and the wireguard-linux-compat kernel module. Restore the original layering: the choice defaults to NONE, and the camera baseline (core.fragment, listed by every camera profile) carries BR2_PACKAGE_THINGINO_VPN_WIREGUARD=y. Camera images are unchanged; toolchain/SDK and other raw defconfigs get no VPN without the package knowing anything about build types.
- 7e438d3 thingino.json: rename button_chime to chime in gpio section The gpio-userkeys generator in ingenic-sdk.mk reads gpio.chime, not gpio.button_chime. Rename the key in all three doorbell camera thingino.json files to match. Signed-off-by: Paul Philippov paul@themactep.com
- f16971c cameras: convert and normalize outdated configs
- fc9ca90 configs: drop redundant uenv.txt files After the gpio sweep, 186 uenv.txt files contained nothing but the comment stub pointing at thingino.json, 9 more carried only serialport=ttyS1 - the exact default common.uenv.txt already sets - and the two jienuo files held only drive-strength comment notes. The build handles a missing camera uenv.txt (CAMERA_UENV_FILE is a $(wildcard) and the copy step is guarded by -f), and plenty of cameras never had one, so drop all 197. Kept: imou_ranger2 (serialport=ttyS0, a real override) and 4 files carrying leftover notes (360_d619 pin notes, wyze_cam3pro_nor commented mmc_power alternatives, cinnado_d1_3k TBD marker).
- b331f9a agents: freshen up onboarding info
- 1f8eee2 restore whole-chip "all" mtdparts alias e08b029 dropped the <flash_size>k@0(all) overlapping partition when the fixed-size layout added "backup". Re-add it in all four generation sites: the uenv.txt mtdparts line, the build info line, the U-Boot CONFIG_MTDPARTS_DEFAULT dev-env patch, and the save_partition_info.py reconstruction (whose flash_kb parameter had been left orphaned). Appended after data it becomes the last MTD, so existing numbering is untouched (root=/dev/mtdblock4, cfg-backup on mtd2). sysupgrade already skips "all" by name in its /proc/mtd walks and prefers it as the full-flash target, so whole-chip flash and dump from Linux work again.
- 17c8718 thingino-uboot: read short-notation gpio.mmc_power c9687dc made bare-int the canonical notation for active-high gpio pins, converting 25 cameras' mmc_power from {pin, active_low: false} objects to plain ints. The vmmc injection only read the object form, so those boards silently lost U-Boot slot power; the hog injector's binding guard had the same dict-only blind spot. Teach both: a bare int is pin + active-high (matching S09mmc's parse_legacy_token default), objects keep carrying active_low, and the multi-pin list form stays with the hog injector. Verified across the fleet: 62 cameras emit vmmc-supply again - the exact coverage from before the notation change - with correct enable-active-high polarity on the short-form boards, and the guard now reserves short-form pins (synthetic wlan/mmc_power collision skips the hog).
- 3f717cd configs: sweep legacy gpio_* lines from wansview_q5 mt7601u uenv The camera arrived via the ciao imports with live gpio_* env lines, pre-sweep style. Every value reconciles against its thingino.json (button_reset 50, leds 72/73 with matching polarity, ircut 79 80, motors, mmc_cd 52), and nothing reads these env keys anymore, so reduce the file to the standard stub like the rest of the fleet.
- 182baea wire libpeer package
- 8173f53 makefile: add build_fast to .PHONY
- e559184 typo
- 1710278 makefile: add bundle- target for making installable bundles
- 91ccf85 remove BR2_PACKAGE_THINGINO_DAYNIGHT from core fragment
- 2caacce remove daynight package reference
- a9e47c5 wpa_supplicant: strip config to only differences
- c67f6d7 install package bundle package
- df01736 misc scripts and helpers from ciao
- 636e08a buildroot: utilities to update submodule (HEAD and by release); formatting
- 5a23dc1 clean up
- db1066a wpa_supplicant: convert to a virtual override package
- 6213e75 system: ease concurect connections on low memory devices
- 25a10d3 network: check for wired interface presence before polling
- dc28fd5 wireless: check for interface in procfs
- a4fff6c ifplugd: install service script override with short opts
- 0d930a8 webui: copy updates from ciao
- f593464 thingino agent: copy updates from ciao
- e671fa8 wyze accessories: copy updates from ciao
- ad2c7d8 home assistant: copy updates from ciao
- 38059a7 install daynightd for prudynt, guard streamer globally
- 75f3b96 gpio: convert to web ui plugin
- 8f2d3ce mqtt: convert to web ui plugin
- b115109 motors: convert to a web ui plugin
- b7c9743 daynight: consolidate daynight and daynightd into one daemon, convert to web ui plugin
- 5ff4115 prudynt: merge changes from ciao branch
- d2436d5 web ui: make paranoid mode a compile time choice
- 6fbefd6 telegrambot: rewrite and convert to a web ui plugin
- b083c25 linux: binary assets for kernel 3.10.14
- 2e13d76 dropbear: drop old version patch
- 11cdc0c privacy: convert to web ui plugin
- ae42ee0 zerotier: convert to web ui plugin
- 4fd3e36 wireguard: convert to web ui plugin
- c407993 move sd card tools to thingino-system gated by BR2_THINGINO_SDCARD
- daa5ee9 remove obsolete ledd
- 752a150 formatting
- c9687dc thingino.json: use short notation for active-high gpio pins
- a8fc480 Merge branch 'master' into soc-per-model-mk
- bbc5ab4 timps: bump TIMPS_VERSION to v1.8.1
- f8fb06e ingenic-sdk: gate the package on the ingenic soc vendor (#1427) BR2_PACKAGE_INGENIC_SDK turns itself on from "default y if !KERNEL_VERSION_7", which keys off the kernel version alone. That condition is true on any SoC vendor, so a package that builds Ingenic kernel modules enables itself on vendors that cannot use it, and each one has to switch it back off in a config fragment -- a workaround every future vendor would have to copy. Config.ingenic.in already selects it inside the Ingenic vendor block, so the selection was vendor-scoped; only the self-enabling default was not. Nothing changes for Ingenic. BR2_SOC_VENDOR is a choice defaulting to BR2_SOC_VENDOR_INGENIC, so every camera defconfig resolves it y and the default still applies. Verified by regenerating .config for all 170 camera defconfigs before and after: byte-identical, including the output directory paths. Co-authored-by: John Chia john@johnchia.com Co-authored-by: Paul Philippov themactep@gmail.com
- b0c0604 Merge branch 'master' into ingenic-sdk-vendor-gate
- f20dc6d motors: convert invert_x/invert_y booleans to integers for SPI modprobe (#1432) SPI motor kernel module expects integer parameters (0/1) for invert_x and invert_y, but jct returns JSON booleans (true/false). Passing false to modprobe causes Invalid argument error, preventing the motor module from loading. Fix: convert true→1, false→0 before passing to modprobe. Reported-by: CaptainRon (Discord) Signed-off-by: WLTB-Gino
- 1621aa6 docs: document doorbell chime volume hardware limitations Add a Hardware limitations section explaining the discrepancy between the protocol byte (0-255), the software range (UI clamps to 1-8, CLI accepts 1-32), and the actual hardware PWM resolution (~4-8 distinct levels). Also update volume references in the parameters table and troubleshooting section. Signed-off-by: Paul Philippov paul@themactep.com
- 36fc6c3 timps: select ingenic-lib libsysutils (fixes link failure) timps/Makefile unconditionally links -lsysutils (IMPLIBS). 96d1311 ("install libsysutils only when selected") flipped BR2_PACKAGE_INGENIC_LIB_LIBSYSUTILS's default from y to n on the assumption that nothing in the tree links it - true for the packages that were in the tree at the time, not for timps (merged in #1438 right after). Breaks every from-scratch TIMPS build right now: "cannot find -lsysutils".
- 09f5595 timps: v1.8.0 - OSD hinting default-on, real build-version reporting, WebUI polish - default BR2_PACKAGE_TIMPS_OSD_HINTING to y (Config.in) - timps.mk: derive VERSION from the real timps git state at parse time instead of the static TIMPS_VERSION tag, so builds using TIMPS_OVERRIDE_SRCDIR report the actual commit (rsync strips .git before the package build sees the source, so git describe has to run before that happens) - GET /control now reports it; small version badge in the footer of every Streamer page and the Preview page (own overlay copy of footer.js, doesn't touch thingino-webui) - preview-timps.html: live Statistics table + bitrate sparkline - config-privacy.html: auto-refresh the mask-editor snapshot every 4s instead of fetching it once
- b282019 webui: fix URL-encoded diagnostic uploads Replace the broken upload_data POST roundtrip with direct_upload, which re-runs thingino-diag -j on the backend. The old path sent diagnostic data URL-encoded through JS -> CGI -> nc, but the CGI's naive eval-based form parser never decoded percent-sequences, resulting in garbled termbin pastes like 'Sat+Aug++8+13%3A55%3A12'. Now the upload button triggers the same clean backend path as the direct_upload checkbox, going thingino-diag -> send2termbin -> nc with no encoding middlemen. Signed-off-by: Paul Philippov paul@themactep.com
- 9f3f8e6 thingino-raptor: bump pins for the comment-preserving config save raptor-common e79a1344: config save edits the file surgically, so comments and hand-edits survive, a save with nothing dirty does not rewrite the file, and the daemons log saved vs untouched truthfully. raptor ee74471a: integration legs for the save logging (tests only).
- edc0d8f ingenic-lib: own the libstdc++ dependencies, drop them from defconfigs The T30 libimp blob (SDK 1.0.5) is the only libimp build that links libstdc++.so.6 - verified by readelf across every family at the exact SDK versions the package installs (t10/t20 3.12.0, t21 1.0.33, t23 1.3.0, t31 1.1.5.2/1.1.6, t40 1.3.1, t41 1.2.6, a1 1.7.0: all clean; t30 1.0.5: NEEDED libstdc++.so.6). The four T30 camera defconfigs each carried BR2_THINGINO_LIBSTDCPP=y to compensate; a library dependency belongs to the package, so select it from BR2_PACKAGE_INGENIC_LIB_LIBIMP when BR2_SOC_FAMILY is t30 (same string-equality pattern the file already uses for the a1 guard) and drop the per-device lines. The stock libaudioProcess blob links libstdc++.so.6 on EVERY family, so the (normally-off - the libaudioprocess-neo rewrite is selected by the streamers and needs only libc) vendor option now selects the C++ runtime too, instead of silently shipping an unloadable blob if someone opts into it. Verified by config resolution: wyze_vdb1_t30x resolves BR2_THINGINO_LIBSTDCPP=y with no defconfig line; t31 control stays unset (neo audioProcess, stock blob off). Converges with feature/figata-fixed-sizes, which already removed the same four defconfig lines without the package-level replacement.
- e9d5824 configs: finish uenv gpio sweep for wuuk_y0941 and cinnado_d13k wuuk_y0941 was untracked during the fleet sweep; now that it is committed, drop its dead gpio_button/gpio_default lines the same way (serialport override stays). Every pin they carried is already in its thingino.json except pin 59 (unidentified rail, parked low - preserved in git history like the other unmapped rails). cinnado_d13k kept a commented-out gpio_default line the sweep's active-line rule skipped; remove it and leave the standard stub. Note for the config author: that rail list carries what looks like PTZ stepper pins (66-69 plus 76/77/83/84) and the json has no motors section - the pan/tilt grouping and order cannot be reconstructed from a park list, so it needs the vendor config.
- 575f998 configs: add exp wuuk y0941
- 3dd69cf configs: drop dead gpio_* lines from uenv.txt files No camera builds the 2013.07 vendor U-Boot (the only U-Boot that read gpio_default/gpio_button/gpio_ircut/gpio_mmc_power/gpio_motor_h/v via handle_gpio_settings): the version choice defaults to 2026.07 and no defconfig overrides it. Mainline U-Boot reads none of these keys, and no script in the shipped rootfs imports gpio_* from the environment - the $gpio_ircut/$gpio_ir850 guards in ircut/daynight/timelapse are relics of the era when init exported uenv vars and are permanently unset on master. Every gpio value these lines carried was reconciled into thingino.json or the kopt defconfig vars first (previous commit ported the 15 orphans), so nothing is lost. Remove all 437 gpio_* assignment lines. Files left empty become a short comment stub pointing at thingino.json so a copied camera dir teaches the convention; the 13 files with other live content (serial port overrides, drive-strength notes) keep it. Build-verified on personal_campan: generated env has no gpio lines, no stub leakage, and all DT inject hooks unchanged.
- 24c64e6 configs: port gpio data that existed only in dead uenv.txt lines No camera builds the 2013.07 vendor U-Boot anymore (the version choice defaults to 2026.07 and no defconfig overrides it), so the gpio_* env lines in uenv.txt are read by nothing. Before they can be swept, a reconciliation of all 437 such lines against thingino.json and the defconfig (LED/audio kopt vars) found 15 values that existed nowhere else. Port them to the live config: - motors gpio_pan/gpio_tilt for 4 PTZ boards that never got a motors section (eufy_t8410 exp, galayou_g2 both variants, wansview_q6), mapped from gpio_motor_h/v - gpio.ttl_1/ttl_2 for vanhua_t55a and vanhua_z66si - BR2_THINGINO_LED_G_GPIO for 360_d619 (73, active low, matching its existing B/R vars) and dekco_t23n (58) Not resolved here, flagged for the config authors: h3c_c2041 and h3c_tc2100 have gpio_motor_h/v exactly swapped against the json gpio_pan/gpio_tilt, and the two galayou_g2 variants disagree with each other the same way - one axis mapping is wrong in each pair.
- 08dc225 thingino-uboot: park IR-cut filter coils at boot Add gpio.ircut (and gpio.ircut_sub) to the boot-window GPIO presets: the filter solenoid sits behind an H-bridge whose inputs float from power-on until the runtime takes over, which can leave a coil partially energised and heating. Park every ircut pin at the /usr/sbin/ircut idle level - dual-pin boards rest both pins at idle between the 10ms pulses and single-pin boards de-energise at the open level, so both reduce to active_low ? HIGH : LOW per pin. The parser mirrors /usr/sbin/ircut exactly: scalar pins, token sequences, {pin, active_low} objects, lists, per-token o/O suffixes (which mean pin POLARITY here - "57o" = active-low = idle HIGH - unlike the drive-level suffixes of gpio.wlan/mmc_power), the 999 tmi8152 kernel-shim sentinel (no gpio), and -1 disabling the whole domain. Swept all 222 build units: strictly additive - every previously emitted node is preserved and only ircut hogs are added (378 pins: 370 low, 8 high on the tapo c500/tc70 suffixed and tapo c100/c110 object boards). No ircut pin collides with an MMC/button DT binding or sits in any U-Boot pinctrl group. Build-verified on personal_campan: ircut_52/ircut_53 output-low in u-boot.dtb next to the 8 motor-park hogs, none in SPL.
- 96d1311 package/ingenic-lib: install libsysutils only when selected No libimp variant in any SoC/SDK/libc combination links or dlopens libsysutils.so, and nothing in the tree links -lsysutils. The default y kept it shipping in every non-a1 image (5.6 KiB flash) since the per-lib split. Default it off and gate the staging install on the same option.
- f7755ef thingino-uboot: never hog a pin owned by an MMC/button DT binding A gpio-hog claims its pin at DM init, so a pin that inject-uboot-mmc-dt.sh also turns into a DT binding (gpio.mmc_cd -> cd-gpios, single-object gpio.mmc_power -> vmmc regulator, gpio.button_reset -> gpio-keys) would make the binding's own gpio request fail and break that subsystem. cinnado_b6 hits this today: its config lists pin 61 as both mmc_cd and a motor phase (config bug, reported to the author), and since the motor coil-park commit the hog has been stealing card-detect from the mmc core in U-Boot. Skip such pins with a build-log note instead - the binding wins, and once the config is fixed the guard is a no-op. Also collapse the same pin appearing in several hog domains to its first occurrence. Re-proven over all 222 build units: cinnado_b6 dropping motor_park_61 is the only output change.
- 738f749 configs: normalize legacy mmc_power notation in cameras-exp Same conversion as the main cameras tree: 8 bare-int mmc_power entries become {pin, active_low: false} objects (bare token = drive high in S09mmc). Proven by replaying get_mmc_power_sequence with host jct over old and new configs: 8/8 identical drive sequences. These boards build through the same U-Boot inject hooks, and the bare-int shape never reached the vmmc-supply injection.
- e32d932 thingino-uboot: unify boot-window GPIO presets in one inject script Replace inject-uboot-motor-dt.sh and inject-uboot-wlan-dt.sh with inject-uboot-gpio-dt.sh, one gpio-hog injector for everything whose job is "drive pin X to level Y and hold it through boot": - motors.gpio_pan/gpio_tilt parked at the kernel driver's de-energised level (gpio_invert aware), as before - gpio.wlan at the final resting level of the S36wireless sequence, as before - NEW: gpio.mmc_power list form - boards whose SD slot needs more than one supply/enable pin get each pin hogged at its power-on level (active_low aware). The single-pin object form intentionally stays in inject-uboot-mmc-dt.sh as a vmmc-supply regulator: the mmc core sequences slot power itself there, which a static hog cannot, but a fixed regulator can only own one gpio, so multi-pin boards get hogs. The two per-domain mk hooks and their config gates collapse into one ungated hook (still skipping the 2013.07 vendor U-Boot, which has its own env-driven gpio_default path). Safe: an audit of all 169 camera configs found zero cameras where a domain emits hogs without its old gate symbol set (BR2_THINGINO_MOTORS / BR2_PACKAGE_WIFI), so gating purely from json content changes no board's output. The script also dedups repeated pins; 9 cameras list identical gpio_pan and gpio_tilt, which previously emitted duplicate same-named nodes that dtc merged - the compiled dtb is identical either way. Proven by regenerating every camera's injection with the old scripts and the new one: 169/169 node-identical after dedup, the only additions being the mmc_power hogs on the 5 multi-pin boards (hl_jdpan01, tapo c100 t23n, wyze_campan2, wyze_vdb2, xiaomi mjsxj05hl). Build-verified on personal_campan (dict mmc_power: vmmc regulator + 8 motor hogs, unchanged) and wyze_campan2 (8 motor + wlan_58 + mmc_power_47/54 hogs in u-boot.dtb, none in SPL).
- 876c3bb configs: normalize legacy gpio token notation to active_low objects The o/O drive-level suffix tokens ("mmc_power": "47o 54o", bare-int "mmc_power": 17) are vendor gpio_default notation; the proper thingino convention is the {pin, active_low} object like the other 31 mmc_power entries already use. Convert: - 17 bare-int entries -> {pin, active_low: false} (bare token = drive high in S09mmc parse_legacy_token) - 5 token strings -> arrays of {pin, active_low} objects (o = drive low = active_low true, O = drive high = active_low false), a shape S09mmc's indexed gpio.mmc_power.N walk already parses natively - ajcloud_cp8040 "wlan": "47O 47o" (high-then-low pulse) -> {pin: 47, active_low: true, toggle: true}, matching its cp2011/cp8010 siblings (S36wireless emits the identical pre-pulse sequence for both forms) Proven equivalent by replaying the real consumers over old and new configs: get_mmc_power_sequence (S09mmc) and get_wlan_sequence (S36wireless) run with host jct produce byte-identical drive sequences for all 23 touched cameras.
- 926072e Generate release artifacts on the MMC boot path The MMC0_BOOT branch of pack: only printed dd instructions and never ran generate_release_artifacts.sh, so no .bin.sha256sum was written. The NAND and NOR branches both call it. firmware-master sets FULL_FW_SHA=${FULL_FW}.sha256sum unconditionally and passes it to gh release upload, which failed the wanjiaan_hdc51 mmc job with "no matches found for ...bin.sha256sum". Previously masked by the earlier parted failure, which killed the job before the release step.
- 869277b thingino-uboot: preset Wi-Fi module GPIO at boot via gpio-hog Some Wi-Fi modules need their power/enable line at a defined level before Linux is up: SDIO parts must be powered so the kernel MMC scan can enumerate them, and S36wireless drives gpio.wlan only on 3.10 kernels, late in boot. Until then the pin sits at the SoC reset default. Add inject-uboot-wlan-dt.sh (sibling of inject-uboot-motor-dt.sh): it reads gpio.wlan from the board's thingino.json in every shape S36wireless.in accepts - bare pin, suffixed token (47o/47O/47t), token sequence, {pin, active_low, toggle, action, state} object, or a list of those - and appends a gpio-hog per pin to this board's U-Boot leaf .dts at the final resting level of the runtime sequence (active_low aware, explicit state wins). A pin whose last action is a toggle depends on prior state and cannot be a static hog, so it is skipped; an object's toggle flag only prepends a pulse and does not change the resting level. The hook is gated on BR2_PACKAGE_WIFI, skips the 2013.07 vendor U-Boot (env gpio_default covers it there), and enables CONFIG_GPIO_HOG so U-Boot acts on the hogs. Hogs land in U-Boot proper only, not SPL. Swept over all camera configs: 121 of 122 gpio.wlan entries emit a hog (90 high / 31 low), the -1 entry emits nothing, and no wlan pin overlaps mmc_cd/mmc_power on any board. Build-verified on personal_campan (no gpio.wlan: clean no-op, motor hogs intact) and wyze_campan2 (wlan 58 -> output-high in u-boot.dtb alongside the 8 motor-park hogs, none in SPL).
- 58b44ee soc: give the c100 its own fragment gtxaspec: the C100 runs 4.4 only. That was the condition the old lookup tested for, so with no second case there is nothing left to test, and the model stops needing an exception inside t31.mk. soc/ingenic/c100.mk states the family outright. It is a t31 part and keeps that arch and U-Boot image, but c100 is a family name openimp.mk, ingenic-lib.mk and Config.soc.in all test for, so it is where a reader will look. t31.mk is left with no exceptions. The family now resolves for real. The old test read KERNEL_VERSION from a file included about thirty lines before thingino.mk resolves it, so it only ever fired when KERNEL_VERSION was passed on the command line; every other path left the family at t31, and openimp and ingenic-lib silently took their T31 arms. No camera defconfig sets BR2_INGENIC_SOC_MODEL="c100", so nothing in tree moves: .config regenerated for all 170, byte-identical.
- e48ae56 soc: say how the c100 family override is activated It fires only when KERNEL_VERSION is passed on the make command line, where it is set before any makefile is read. thingino.mk resolves KERNEL_VERSION after the SoC fragments, so nothing else reaches this test -- which is acceptable for one model, and cheaper than machinery in the shared file.
- d55b693 Revert "soc: resolve the c100 family after the kernel version is known" This reverts commit 91ba604.
- 49a00f2 ingenic-sdk: gate the package on the ingenic soc vendor BR2_PACKAGE_INGENIC_SDK turns itself on from "default y if !KERNEL_VERSION_7", which keys off the kernel version alone. That condition is true on any SoC vendor, so a package that builds Ingenic kernel modules enables itself on vendors that cannot use it, and each one has to switch it back off in a config fragment -- a workaround every future vendor would have to copy. Config.ingenic.in already selects it inside the Ingenic vendor block, so the selection was vendor-scoped; only the self-enabling default was not. Nothing changes for Ingenic. BR2_SOC_VENDOR is a choice defaulting to BR2_SOC_VENDOR_INGENIC, so every camera defconfig resolves it y and the default still applies. Verified by regenerating .config for all 170 camera defconfigs before and after: byte-identical, including the output directory paths.
- 91ba604 soc: resolve the c100 family after the kernel version is known The c100 override tested KERNEL_VERSION from inside a SoC fragment, which thingino.mk includes about thirty lines before KERNEL_VERSION is resolved. Make evaluates ifeq at parse time, so the variable was empty and the override did not fire -- except when KERNEL_VERSION is passed on the command line, where it is defined before any makefile is read. On every other path, including the KERNEL_VERSION_4 that Config.soc.in defaults c100 to, SOC_FAMILY stayed t31: openimp built for T31 and ingenic-lib took the T31 SDK path. The ordering is carried over from the lookup this series replaces, so it is not a regression, but the rewrite is the moment to fix it. The cycle is real -- KERNEL_VERSION keys off SOC_FAMILY for t40, t41 and a1, so the fragments have to be read first -- so a fragment now states the dependency as data and thingino.mk applies it once KERNEL_VERSION is known. That keeps the fact with the SoC and leaves the shared file generic. SOC_FAMILY_CAPS moves below the override, being an immediate assignment. c100 gets its own fragment rather than riding along in t31.mk. It is a family name three consumers already test for, so it is where a reader looks, and it leaves t31.mk with no exceptions. The fragment declares family t31, which is what the soc_database.txt row said; only the kernel promotes it. No camera defconfig sets BR2_INGENIC_SOC_MODEL="c100", so nothing in tree changes and the c100 path stays untested by the sweep. Verified with a throwaway defconfig instead: SOC_FAMILY is t31 by default, and c100 both when KERNEL_VERSION_4=y and when KERNEL_VERSION=4.4.94 -- the middle case being the one that was broken.
- 9dde97c docs: name the SoC fragments by family in AGENTS.md The fragments are one per family, not one per model, and all of them are included -- the $(filter) opening each is what selects the body.
- f3f1d4c sensor: handle both suffixed and unsuffixed /proc/jz/sensor layouts The kernel can expose /proc/jz/sensor in two formats: - suffixed: numbered subdirs like sensor0/ with a count file - unsuffixed: sensor attributes directly in /proc/jz/sensor/ Make the sensor script auto-detect the layout at runtime, and add a fallback to the two CGI scripts so they try sensor0/name first then name for the unsuffixed case. Signed-off-by: Paul Philippov paul@themactep.com
- e092d7b package/dropbear: drop patched for older versions
- 287bf96 list of files for backup partition
- e08b029 fixed size partitioning, kernel and uboot from tarballs with patches
- 6b39316 escape doublequotes in common uenv.txt
- f3caeab remove motors from common thingino.json, not every camera has motors
- 0360a6f mmc: check for actual endpoint, not just the value
- 3639622 onvif: rewrite notify service script
- 19fbe90 onvif: patched in the repo
- e056396 package/jct: add missing .hash file
- d25f1a5 thingino-button: block in poll() instead of busy-polling the input device
- e70ecea cameras: adjust memory mapping on xiaomi mjsxj03hl and noname t10
- 6eb502c cameras: preset stream and rotation parameters on doorbell cameras
- 81411f0 cameras: add wansview q5 t21n variant
- d26daf4 formatting
- 3204102 cameras: correct mmc_cd gpio on wyze cam pan 1
- 0bdd8cf soc: group the SoC fragments by family rather than by model 54 files down to 11, one per Ingenic family, each holding a block per model. Same variables, same consumers, same values. Grouping pays for itself beyond the file count: family, arch and the U-Boot image name are uniform across every model in a family -- checked against the old database, not assumed -- so each is stated once at the top of the file instead of being repeated on every model. Only RAM and the U-Boot board names actually vary, and those keep a block each. The include changes shape. A per-model file could be named from SOC_MODEL and included directly; a per-family file cannot, because the family is one of the things being looked up. So all of them are included and each opens with a $(filter) on its own models, leaving exactly one body live. That moves where an unknown model is caught. There is no longer a missing file to test for, so the check is that nothing claimed the model and SOC_FAMILY came out empty. Same outcome -- the build stops naming the model -- rather than the old fallback to "unknown"/64, which built something wrong. Verified: .config regenerated for all 170 camera defconfigs, byte-identical to the pre-change baseline for every one.
- c620ffb cameras: fix reset button gpio definition on WUUK cameras
- 7ffb3a3 cameras: remove BR2_THINGINO_LIBSTDCPP=y from defconfigs
- aaae948 soc: drop what was left pointing at the SoC database Follow-on to the previous commit. Deleting soc_database.txt and its scripts left several places referring to files that no longer exist. scripts/thingino_soc_section_example.mk called get_soc_params.sh and existed only as a worked example of the design being replaced, so it goes. The four docs/ai/ files on the subject -- SOC_DATABASE_SUMMARY, README_SOC_DATABASE, IMPLEMENTATION_GUIDE and INGENIC_SOC_MODEL_IMPLEMENTATION -- document the database, the query script and that example end to end. With those removed the documents instruct the reader to run commands that are gone, which is worse than not having them; git history keeps the migration record. The two unrelated files in docs/ai/ stay. AGENTS.md described the family as coming from Config.soc.in and the database. It now describes both halves as they are, including that adding a SoC means editing Config.soc.in and soc//, because neither can read the other. Two comments reworded, in Config.ingenic.in and flash-nand.fragment. grep -rn "get_soc_params|soc_database" now returns nothing. Verified: .config regenerated for all 170 camera defconfigs, byte-identical. Re-run rather than assumed, because fragment comments are appended to .config and flash-nand.fragment is one of the files touched -- no board enables NAND, so it never reaches a config, but that is a property of the fleet rather than of the change.
- c89ec66 soc: replace soc_database.txt with one makefile fragment per soc The SoC table was a CSV with a hand-rolled awk parser and a bespoke validator to check the CSV was well-formed. Make can express the same table natively, so all three go: soc//.mk sets the variables and thingino.mk includes the one it needs. Removes scripts/get_soc_params.sh (77 lines), scripts/validate_soc_database.sh (82) and scripts/soc_database.txt (85), and takes the seven bash+awk forks per make invocation to zero. The validator only existed because the format was untyped text; make checks the syntax itself. Beyond the line count: - No fixed column set. A SoC needing one more fact sets one more variable, rather than a column being added to all 54 rows and to the validator. - No "-" sentinels. A SoC with no separate NAND board does not set SOC_UBOOT_NAND, and the consumer falls back with $(or ...) -- which is what the "-" meant. - The C100 special case lives in soc/ingenic/c100.mk. Its family depends on the kernel version, so it had to be a special case in the shared dispatch. - An unknown model stops the build naming the file it wanted, instead of falling back to "unknown"/64 and building something wrong. The wildcard guard around the include is deliberately unindented: a tab-led $(error ...) is not a directive, so make reads it as a recipe and fails with "recipe commences before first target". This does not remove the duplicate model->family map. Config.soc.in keeps its own copy driving BR2_SOC_FAMILY in .config, and has to -- Kconfig cannot run make, and thingino.mk needs SOC_FAMILY before .config exists because OUTPUT_DIR is derived from it. Only make's copy moves. Verified: .config regenerated for all 170 camera defconfigs, before and after, byte-identical for every one, both sides on the same branch so OUTPUT_DIR does not move. SOC_ARCH reaches the toolchain tag unchanged across the fleet -- 168 boards xburst1, 2 xburst2 -- matching the old xburst$(...) prefixing. Not build-tested: no camera defconfig sets BR2_THINGINO_FLASH_NAND=y, so SOC_UBOOT_NAND and the NAND arm of UBOOT_DEFCONFIG are transcription checked against the column the old script read, not exercised.
- 4f0c676 expang package update script to handle realeases, create .hash files
- dcd62fe add human readable camera hardware to os-release
- 1f444d1 clean up a c++ gdb python helpers of any version
- 21bf452 add helper script for git workspaces
- 89e3eb1 make gpio tabulator aware of new env file names
- 5ab4274 add SEI scripts and tools
- 0f5abd5 shell formatting
- 4b19990 add test scripts for onvif backchannel
- d54196c container: handle IP argument correctly
- 99f18ef cameras: rename named uenv.txt files to just uenv.txt in camera's directory cameras-exp: rename named uenv.txt files to just uenv.txt in camera's directory
- 26ce5f5 makefile: regenerate uent.txt or rebuild/repack, escape double-quotes
- d42df98 makefile: pick up prefixed ouput directory from env (THINGINO_OUTPUT_ROOT_DIR)
- 3db9a21 makefile: default to u-boot 2026.07
- ebc28c4 makefile: default to uclibc
- b1d25e0 makefile: skip dependency check for make update
- 5827105 strero: copy updates from ciao
- bb14f91 install onvif server for any ip camera
- 3283acb add mbedtls-certgen bundle rules
- cc37f63 add go2rtc bundle rules
- 58264fc add plog package v1.1.11
- 22603f4 add thingino-snmpd package
- aa791cf add package bundle system
- 0bda686 webui: motors: skip tilt validation on pan-only cameras When all tilt GPIOs are -1 the hardware has no tilt axis and steps_tilt = 0 is legitimate. Skip tilt GPIO and steps validation in that case instead of blocking the entire form with "Tilt max steps must be a positive number". Also fix the error display: the fallback showAlert used textContent which rendered
tags literally. Show each validation error as a separate alert instead. Closes #1402 Signed-off-by: Paul Philippov paul@themactep.com - a221cb8 cameras: preset t10/t20 units to 20 fps and 16k audio bitrate to lower cpu load
- c2f629f thingino-diag: redact SSID and encryption key from WIFI-INFO output Pipe iw/iwconfig output through sed to redact sensitive fields: - ESSID (iwconfig) / ssid (iw) - Encryption key (iwconfig) Matches existing redaction patterns used for WPA-STATUS and WPA-CONF. Signed-off-by: Paul Philippov paul@themactep.com
- 7ab5df5 thingino-diag: redact SSID and encryption key from WIFI-INFO output Pipe iw/iwconfig output through sed to redact sensitive fields: - ESSID (iwconfig) / ssid (iw) - Encryption key (iwconfig) Matches existing redaction patterns used for WPA-STATUS and WPA-CONF. Signed-off-by: Paul Philippov paul@themactep.com
- 78f2d38 agents: add ascii only rule for scripting
- 698d5de wifi: skip wired uplink polling when no wired interfaces exist Add any_wired_iface_exists() guard that checks whether eth0 or usb0 exist before entering the 10-second polling loop. On Wi-Fi-only cameras (no wired interfaces) watch_wired_uplink returns immediately instead of wasting 10 seconds in a futile poll. Signed-off-by: Paul Philippov paul@themactep.com
- 281d79f telegrambot: substitute $chat_id in command strings before execution The run_command() function was passing command strings verbatim to popen(), so $chat_id was never expanded. Replace every occurrence of the literal $chat_id with the actual numeric chat ID value before the shell sees the command. Fixes #1367 Signed-off-by: Paul Philippov paul@themactep.com
- 5f89383 thingino-diag: add wireless information thingino-diag: redact raw hex PSK and add overlay tree dump Redact unquoted 64-char hex PSK values in wpa_supplicant.conf that were leaking through the existing quoted-psk-only sed pattern. Also add a tree /overlay/ section so diagnostics include the overlay filesystem contents. Signed-off-by: Paul Philippov paul@themactep.com
- c2bbc20 thingino-core: fix camera config merge order Camera thingino.json was staged as 10-camera.json, which sorted before all package defaults (20-, 30-, 40-, 50-). This caused package defaults with empty hardware-specific values (e.g., gpio_pan, gpio_tilt, gpio_switch from motors.json) to overwrite the camera's real GPIO pin configuration. Rename to 90-camera.json so the camera config overrides all package defaults, but still runs before user configs. Signed-off-by: Paul Philippov paul@themactep.com
- 8c654c6 agents: add note about grepping output
- dc768a9 config-network: fix hostname pattern attribute for unicodeSets (v flag) The pattern [A-Za-z0-9.-]+ fails under the v (unicodeSets) regex flag used by modern browsers for HTML pattern validation. The unescaped hyphen and dot cause a SyntaxError when the input field is focused. Escape both characters: [A-Za-z0-9-.]+ Signed-off-by: Paul Philippov paul@themactep.com
- c3c9473 fix wireless portal start
- b1622eb extract ipv6 support and bind it to BR2_PACKAGE_THINGINO_KOPT_IPV6, enabled by default fix: create if-down.d directory before IPv6 odhcp6c symlink The THINGINO_KOPT_INSTALL_TARGET_CMDS_IPV6 block installs odhcp6c into if-up.d (which -D creates on demand) but then tries to symlink it into if-down.d without ensuring that directory exists, causing: ln: failed to create symbolic link '.../if-down.d/odhcp6c': No such file or directory Add mkdir -p for if-down.d before the ln -sf. Signed-off-by: Paul Philippov paul@themactep.com fix: also create interfaces.d directory for IPv6 eth0 config Following up on the if-down.d fix, the echo append to interfaces.d/eth0 also fails when the directory doesn't exist yet in the per-package staging area (the overlay provides it later). Add interfaces.d to the mkdir -p alongside if-down.d. Signed-off-by: Paul Philippov paul@themactep.com