hilink-urllc
18
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c98adedbeb |
apfpv: stop writing outgoing.enabled, which majestic no longer has (#158)
`outgoing.enabled` was one switch for the whole list of places a camera publishes to. Each destination has carried its own since OpenIPC/majestic#701, and the section switch was removed rather than kept as a second gate — so this line writes a key nothing reads. majestic strips it from the tree on load and the next save drops it from the file. The `.outgoing.server` line below it stays and is untouched: `cli` edits majestic.yaml directly, majestic converts that address into a row of its destination list on load, and the camera publishes exactly as before. There is no way to write a list element through yaml-cli — its path validator rejects the brackets — so the single-address spelling is the one this script must keep using. |
||
|
|
ba182ac589 |
excludes: strip two sensors these boards cannot use, and a dead f2fs entry (#155)
sensor_sc3336_mipi.ko, sensor_os03b10_mipi.ko and sc3336.bin arrived in sigmastar-osdrv-sensors after the ssc333 exclude lists were written, so meari-speed-6s (JXF37) and babysense-see-hd-ip206 (GC2053) have been shipping both sensors they cannot use. No board in the README table uses SC3336 or OS03B10. Scoped to those two devices on purpose. The other nine infinity6b0 profiles carry the same two files, but ssc333_lite_tp-link-tapo-c110-v26 has "?" in the sensor column and stripping a sensor blob from a board whose sensor nobody has recorded is not a safe guess. f2fs.ko has not been built since F2FS was switched off upstream (# CONFIG_F2FS_FS is not set in hi3518ev200.generic.config), so five hi3518ev200_lite lists have been asking the rootfs script to delete a file that is never there, and every build prints "1 of 55 entries matched no file" for it. The warning is how a stale exclude gets noticed, so it should not be permanently on. Measured by rebuilding the shipped nightly-20260909-e0a643f images with the build's own squashfs parameters (the unmodified tree reproduces them byte-exactly): meari 5108 -> 5092 KB, babysense 5104 -> 5092 KB. |
||
|
|
2a26e86e45 |
gk7205v200_otg: stop the UVC gadget freeing its own video device (#149)
Tearing down a UVC gadget that userspace still has open corrupts the V4L2 core: the node number leaks (the gadget climbs /dev/video0 -> video1 -> video2 across role switches), and once the kernel is tainted by the WARN that goes with it, a NULL dereference follows with v4l2_device_release on the backtrace. struct uvc_device embeds its struct video_device and uvc_free() kfree()s the lot, but the V4L2 core holds a reference to that video_device for as long as /dev/videoN is open. Reference-count the structure instead, which is what the driver's own "TODO reference counting" has been asking for. Verified on the bench: the gadget returns to /dev/video0 every time instead of climbing, and no WARN or Oops after repeated switching. |
||
|
|
0df089bf61 |
gk7205v200_otg: take the role scripts from firmware's package (#148)
Follow-up to OpenIPC/firmware#2370, which moves `usb-mode`, `uvc-gadget-setup` and `S72usbmode` into a selectable `usb-dual-role` package. Nothing about them was device-specific; they were only here because this is where the OTG image was first put together. So this profile stops carrying its own copies and selects the package instead. Keeping both would be worse than untidy: firmware installs them in /usr/sbin and this profile installed them in /usr/bin, so a build with both would put two versions of each script on the camera and let PATH order decide which ran -- with the copy here being the older, missing the bus settling, the UDC guard and the idempotent apply that came with the move. MERGE AFTER the firmware change, not before: until that lands there is no package to select, and a build from this branch ships no role scripts at all. What stays here is what is genuinely particular to this board: the defconfig, the kernel config, and the dwc3/uvc patches. |
||
|
|
f86ea4f4a6 |
gk7205v200_otg: settle the USB role before xHCI probes (#147)
The OTG profile could not see USB devices in host mode. On a board with a UVC webcam on the USB tail, `lsusb` showed only the two root hubs, while the same board running a plain lite image enumerated the webcam normally. The controller was in the host role and the host controller was running -- mode file "host", xhci-hcd bound, USBCMD 0x5, PORTSC1 port-power set -- and the port still never reported a connect (PORTSC1 0x00000280, CCS clear). dr_mode = "otg" makes dwc3_core_init() program GCTL.PRTCAPDIR = OTG(3), and dwc3_core_init_mode() registers xhci-hcd on top of that. This 4.9 dwc3 has no working OTG role-detection block, so xHCI probes, resets the controller and brings up its root hubs while the core is in a role it cannot drive. The port is then dead for the life of that probe. S72usbmode's `usb-mode host` did not repair it and could not: writing the debugfs mode file reaches dwc3_set_mode(), which flips GCTL.PRTCAPDIR and nothing else, leaving the already-probed xHCI with the port state machine it built in OTG. It also skipped the bind, because xhci-hcd was already bound. Fix it where the ordering is: patch dwc3_core_init() to program PRTCAPDIR = HOST for the OTG case, so xHCI probes into a role the core can drive. dwc3_gadget_init() only registers a UDC and does not care, and `usb-mode device` re-aims the controller itself when it takes the port. usb-mode's host path also learns to re-probe an xHCI that was bound in some other role, which is what makes a newer rootfs recover on an older kernel. |
||
|
|
bac7c697b2 |
xm-85h50ai: turn on majestic's autofocus out of the box (#142)
The first camera with working autofocus on HiSilicon: the customizer enables majestic's contrast AF engine (widgetii/majestic#522), which reads the ISP's BE AF zone statistics and drives this board's XM zoom block over the same UART the pad uses, serialised by the same lock. The engine defaults to off everywhere — a lens without a focus motor must not grow an /autofocus endpoint — so enabling it in the profile of the board it was proven on is the whole change; port and speed defaults already match. The WebUI grows an AF button and books a settle-gated pass after each zoom step (majestic-webui#265). Verified end to end on the lab unit: from total blur to a tack-sharp frame, fv 30 -> 5126 against a 5606 peak in 21s. |
||
|
|
3921b342f3 |
Add hi3516ev300_lite_xm-85h50ai device profile (XiongMai, motorized zoom+focus) (#141)
XiongMai's 85H50AI: hi3516ev300 + imx335 with a motorized zoom/focus module whose MCU shares /dev/ttyAMA0 with the serial console at 115200, speaking the XM near-Pelco protocol (majestic-webui's btzoom-xm). Proven on a lab unit driven end to end through the WebUI (majestic-webui#227). The defconfig is a byte-copy of firmware's hi3516ev300_lite_defconfig. customizer.sh (first boot) sets sensor imx335, the upgrade URL, and the PTZ trio — ptz_control pelco-xm, ptz_port /dev/ttyAMA0, ptz_caps 'zoom focus' (majestic-webui#261) — and deletes the getty line from /etc/inittab: the MCU owns the console UART. The edit lands in the overlay and heals itself (an upgrade that wipes the overlay wipes /etc/custom.ok too, so the script re-runs). S01printk quiets runtime kernel messages that would drip onto the PTZ wire. The required hi3516ev300_lite excludes list prunes every non-imx335 sensor blob, generated from the live lite image so no entry is stale on arrival. |
||
|
|
b2267404b9 |
customizer: gpio_motors becomes ptz_gpio, with ptz_control naming the method (#140)
Completes the #227 PTZ env rename (majestic-webui#232, firmware#2341) in the last place still writing the old name: the three customizer.sh files carrying 'fw_setenv gpio_motors ...' now write ptz_gpio instead. The gpio-motors utility reads ptz_gpio first and falls back to gpio_motors since firmware#2341, and it is the only consumer of the variable anywhere in the org, so the rename is mechanical. Each device also gains 'fw_setenv ptz_control gpio' — not part of the rename, but required by it: the WebUI dropped its auto-detection from a bare pin list (unset ptz_control now means no PTZ, per flyrouter's ruling on the same issue; majestic-webui#255). Without the method named, these devices would keep their motors but lose their pads. In t23_lite_jooan-a6m-u the pin line was commented out, so both new lines are commented there too. |
||
|
|
2b619b9e76 |
publish with an explicit release credential, and prove it before building (#138)
* publish with an explicit release credential, and prove it before building
This repo was next in line for the failure OpenIPC/firmware hit on
2026-08-29. Moving the nightly off `schedule:` onto a dispatch changes
the identity the run executes as, and the default GITHUB_TOKEN's
release-write goes with it: a scheduled run executes as the repository's
scheduling identity, a dispatched one as whoever dispatched it, and for
an app/OAuth-backed identity the releases API answers 403 "Resource not
accessible by integration".
It does so even though the job declares `contents: write` and the run
log confirms the token was granted it, which is why nothing in the
workflow file looks wrong. firmware's run 33273333359 built 102 boards
over two hours before finding out. This repo builds 107 devices and
publishes the same way -- `gh release create` plus a PATCH of
refs/tags/latest -- so it would have failed identically the first time
the train reached it. It never got that far only because the train
correctly refused to advance past firmware's failure.
The publish step takes RELEASE_TOKEN instead of the default token, and
preflight proves that credential can create a release before the matrix
is allowed to spend hours on it, by creating a draft release and
deleting it: invisible, no tag, two API calls.
Asserting the secret is merely non-empty would not have caught the
firmware incident. The token that failed existed and was simply refused,
so the probe has to attempt the write.
* probe: survive re-runs and clean up after itself
Review caught a real defect in the credential probe. It deleted its
draft with a single fail-fast call, so an interrupted or cancelled job
left the draft behind -- and because github.run_id is stable across
re-runs, that leftover would collide with its own re-run and report a
perfectly good credential as broken. A guard that fails wrongly is worse
than no guard, because it blocks good runs and teaches people to ignore
it.
Three changes. The probe tag now carries run_attempt as well as run_id,
so a re-run can never collide with its own leftovers. Deletion moved
into a trap, so a cancelled job still cleans up. And a best-effort sweep
removes probe drafts stranded by earlier runs, because cleanup.yml does
not know this tag pattern and they would otherwise accumulate forever.
The sweep is capped at the 10 most recent releases and swallows every
error. That cap is not arbitrary: listing 100 releases in these repos
returns HTTP 504 because each carries hundreds of assets, measured at
~2s for 10 and ~7s for 30. Housekeeping must never be the thing that
fails a build.
Verified end to end against the live repo with a real token: creates the
draft, reports "release credential OK", the trap removes it, no tag is
created and no published release is touched. Both failure paths still
fail loudly -- unset token, and a credential the API refuses.
* probe: retry the write, and do not narrate garbage while sweeping
Review caught that the probe treated any one-shot POST failure as a bad
credential. GitHub answers 403 for secondary rate limiting as well as
for refusal -- the publish step retries six times for exactly that
reason -- and these repos return 504 on ordinary release listings often
enough that one was hit while writing this change. A blip would have
failed the nightly with "the token is wrong", sending whoever read it
off to reissue a credential that was never the problem.
The POST now retries three times with 5s and 10s backoff, and the error
says "after 3 attempts ... if this is not a transient API error". Three
rather than the publish step`s six because the value here is failing
fast: a genuine misconfiguration still surfaces in well under a minute
instead of after the whole matrix.
Testing the retry then exposed a second defect, in the sweep added by
the previous commit. gh writes its error body to STDOUT, so a failed
list feeds the cleanup loop lines of JSON instead of release ids, and
the log filled with `removing stranded probe draft {"status": "401"}`.
The deletes were harmless -- they simply failed -- but a step whose
entire purpose is to be believed must not narrate confident nonsense.
Only numeric ids are acted on now.
Verified against the live repo: happy path creates the draft, reports
OK, the trap removes it, nothing is left behind; a refused credential
retries three times and fails with the honest message; a failing list
produces zero bogus removal lines.
|
||
|
|
96fc55698c |
Take the nightly off GitHub's scheduler (#137)
This is the last stage of a three-stage release train — widgetii/majestic publishes the majestic tarball, OpenIPC/firmware builds the images, this builds from that tree. Each stage was its own GitHub cron sized against a guess at the previous stage's runtime: 17:25, 22:30 and 03:00 UTC. From 2026-08-26 GitHub began delivering scheduled events hours late and independently per repo, and this repository was the worst affected of the three — +10h38m and +11h49m on successive nights, a 03:00 slot sitting in the deepest part of the congestion band. On the 08-28 cycle that made this stage run FIRST, at 14:49, ahead of both the repositories it is supposed to follow. It went green, as it always would: no stage checks that its inputs are newer than the ones it used last time. The delay is not ours and not fixable here: for every late run `created_at == run_started_at` to the second, so all of it sits upstream of run creation, inside GitHub's dispatcher. Moving the cron off the top of the hour and pushing a commit to resync the schedule were both tried on the majestic side; neither changed anything. The ordering moves to the host that runs majestic's self-hosted runners, which dispatches each stage in turn and waits for it to succeed before starting the next. Unlike majestic and firmware this needed no gate change, and the preflight comment now says why: those two skip when nothing has changed and keyed that skip on the event name, which a dispatch would have made unreachable. This one deliberately always builds, so there was no event-name condition to go stale. The clone guard rail keeps its logic and loses half its argument: an inherited workflow can no longer run nightly and unattended on a stranger's Actions bill, but it can still do so on every internal PR. |
||
|
|
9df259cb6f |
ci: build the KC110 and the Tapo TC70 v3 instead of skipping them (#132)
Both devices have had a complete devices/<dir>/ in this tree for a long time and had never once been built. #120 froze that state rather than changing it -- it put the 7 defconfigs that were in no master.yml matrix into NOT_BUILT so that a device falling out of CI would be a test failure instead of a silent skip. Freezing was right for a change whose job was to not alter what gets built; it was never meant to be permanent for devices whose only problem is that nobody added the matrix line. Two contributors did try to add that line. #111 (Tapo TC70 v3, July) and #108 (KC110, June) both append to the device list in master.yml, which is where the registry lived when they were written. It does not live there any more -- the matrix is read off the tree -- so both PRs are merge conflicts now, and the devices they asked for are exactly the two entries removed here. This is their CI half, landed the way the selector wants it. #108 also carries a BR2_OPENIPC_MAJESTIC="ultimate" line and a vendor libsns_ov2735.so for the no-video bug; those are unaffected and stay with that PR. The two self-test cases that used t31_lite_tp-link-tapo-tc70-v3 as their example of an unbuilt device move to t31_lite_xiaomi-mjsxj05hl, which is still in NOT_BUILT. The overlay case also switches to a path that exists, since the device it now names has no etc/inittab. Neither device had ever been through a build, so this PR was where we found out. That was affordable exactly once: a change to ci-matrix.py cannot narrow -- it is what does the narrowing -- so this ran the full matrix and proved both in the same run. Both are green: Firmware (hi3518ev200_ultimate_tplink-kasa-kc110) SUCCESS Firmware (t31_lite_tp-link-tapo-tc70-v3) SUCCESS |
||
|
|
5e2d58f644 |
fpv: give the 8812eu its own gk7205v200 build (#133)
#61 asks for 8812eu support on gk7205v200 FPV. #70 and the first version of this PR both tried to satisfy it by adding BR2_PACKAGE_RTL88X2EU_OPENIPC=y next to the existing BR2_PACKAGE_RTL8812AU_OPENIPC=y. CI built that and it does not fit: - uImage: [1988KB/2048KB] - rootfs.squashfs: [5504KB/5120KB] -- size exceeded by: 384KB Two heavy kernel Wi-Fi drivers do not go in one 8M image. The driver itself is fine -- 8812eu.ko links and installs -- it is purely flash budget, and there is no 384KB of slack in a 5MB rootfs that was already at its cap. The tree had already said so. Every defconfig here that ships both drivers is 16M: the ssc338q, ssc30kq, ssc377qe and ssc378qe fpv/apfpv/rubyfpv targets. Every 8M one ships 8812au alone: gk7205v200/v210/v300 fpv and venc, hi3516ev200_fpv, hi3516ev300_fpv. The "missing" 8812eu on the Goke configs was never an oversight; it is what 8M allows. So this is a separate build. gk7205v200_fpv_8812eu is gk7205v200_fpv with one line changed, the driver swapped rather than added: -BR2_PACKAGE_RTL8812AU_OPENIPC=y +BR2_PACKAGE_RTL88X2EU_OPENIPC=y The existing gk7205v200_fpv is untouched, so nobody on an 8812au adapter is affected. It builds with room to spare -- rootfs 5024KB/5120KB, 96KB headroom. Nothing else had to move for it: - Registration is automatic; the defconfig is the registration. --self-test passes at 108 devices and the diff narrows to exactly this target, so its own build proved it. - Excludes resolve as ${OPENIPC_SOC_MODEL}_${OPENIPC_VARIANT}.list in firmware's rootfs_script.sh, and VARIANT stays "fpv", so it reuses gk7205v200_fpv.list. That list strips neither driver. - Release assets do not collide. master.yml keys on the underscore count: gk7205v200_fpv is COMMON=1 and uploads the canonical openipc.gk7205v200-nor-fpv.tgz, this one is COMMON=2 and is renamed to gk7205v200_fpv_8812eu-nor.tgz. Same for its sizes.json. Only gk7205v200, which is what #61 asked for. The other four 8M FPV targets have the same constraint and could take the same treatment if anyone asks. Closes #70. |
||
|
|
82ab2e7a32 |
docs: stop telling contributors to register a device in master.yml (#134)
Step 6 of "Adding a new device" still said to add `- <device>` to the matrix in .github/workflows/master.yml, and called that matrix "the *only* build registry". Neither has been true since #120 moved the matrix into .github/scripts/ci-matrix.py, where it is derived from the tree rather than listed. master.yml has no device list at all. Not a hypothetical staleness: #111 (Tapo TC70 v3) and #108 (KC110) each append a line to a block that no longer exists, so both are merge conflicts rather than the one-line changes they were written as. Their authors did the documented thing. So step 6 is now the opposite instruction -- there is nothing to add, and adding it is the mistake. It also names NOT_BUILT, since that is the one list a contributor could reasonably go looking for, and says to leave it alone. Two adjacent claims went stale with the same change: the master.yml bullet described a cron-and-dispatch workflow with no pull_request trigger, and nothing mentioned ci-matrix.py at all -- including that --self-test runs in the Select devices job and will fail a PR that puts the tree and the selector out of step. A second correction, caught by Qodo in review: "opening the PR is what gets the device built" holds only for a non-draft PR. classify() returns needs_build=False for a draft and self_test() asserts it; master.yml lists ready_for_review in its triggers precisely because a PR opened as a draft would otherwise never build once marked ready. Left as written, a contributor could open a draft, see no build, and read that as the device being fine. The ci:full label is documented for the same reason -- it is the other contributor-facing lever over the matrix. |
||
|
|
6fef62c0f3 |
ci: watch for drift from firmware instead of finding it by accident (#129)
* ci: watch for drift from firmware instead of finding it by accident builder.sh copies devices/<item>/* over a fresh firmware clone, so a device directory that ships its own copy of a firmware file replaces it outright. A fleet-wide change in firmware reaches every device that only references a path and none that ships its own copy, silently, because nothing in either repository is looking. One comment on OpenIPC/firmware#2308 turned up three instances of that in an afternoon: 13 board configs that missed the CONFIG_VT sweep (#126), 97 defconfigs that kept BR2_PACKAGE_JSONFILTER after firmware retired it and put three devices over their rootfs cap (#128), and excludes lists naming files that no longer exist (firmware#2313 reports those at build time). The trigger is the design. Every one of those was caused by a commit in firmware while this repository sat untouched, so a pull_request check would never have fired for any of them -- nobody opens a builder PR when firmware changes. firmware-drift.yml runs on a schedule and files an issue rather than failing: drift someone else introduced is not a reason to redden a nightly that is otherwise fine. Only the self-test gates a merge here, out of lint.yml. Two checks, because the two kinds of drift are not the same shape. Shadowed files: comparing content is useless, a builder copy is *supposed* to differ. What matters is whether firmware's version moved since a human last reconciled them, so each of the 13 entries pins the blob it was reconciled against. Re-pinning is the act of looking again. The mapping is hand-authored -- nothing can infer that gk7205v200.generic-fpv derives from gk7205v200.generic. Defconfig symbols: nothing here copies a firmware defconfig, so pinning does not apply. Every BR2_PACKAGE_*=y is resolved against buildroot, firmware and this tree and sorted into "resolves nowhere" (a dead line kconfig ignores) and "resolves, but no firmware defconfig selects it" (needs an allowlist entry). An allowlist entry can also fence a symbol to the devices that need it; without that, writing JSONFILTER down as builder-only for devices/apfpv would equally bless it creeping back onto 95 unrelated defconfigs, which is #128 verbatim. Replayed against the three regressions, each reproduced by hand on a clean tree: firmware moves a shadowed config -> br-ext-chip-goke/board/gk7205v200/gk7205v200.generic.config moved in firmware since this copy was reconciled (2026-08-25). builder copy: devices/common/.../gk7205v200.generic-fpv.config pinned 7450c6803f6d, firmware now f97dce84c0f8 firmware commits since: 85233f0e kernel: drop CONFIG_VT and the busybox applets ... (#2308) jsonfilter creeps back onto a non-apfpv device -> BR2_PACKAGE_JSONFILTER is allowlisted only for apfpv/*/configs/*_defconfig, but 1 other defconfig(s) select it. firmware retires a symbol builder still selects -> BR2_PACKAGE_LIBUBOX is selected here but by no firmware defconfig. Resolving against buildroot is not optional and getting it wrong is how a checker lies. Buildroot is vendored by neither repository, so a first pass over OpenIPC packages alone called HOSTAPD, IW, PHP, UHTTPD, LIBZIP and BWM_NG dead; all six are upstream. Matching only "Config.in" then called PHP_EXT_ZIP dead, because buildroot declares php's extensions in package/php/Config.ext. Without --buildroot that half is skipped and says so rather than inventing findings. Two symbols really do resolve nowhere today -- BR2_PACKAGE_APFPV_GREG on the four greg-generic devices and BR2_PACKAGE_WIFIBROADCAST_EXT in devices/common. Both are recorded as known-dead and reported as a notice on every run rather than removed: whether those devices still want the packages is a maintainer's call, not a side effect of adding a check. The three new paths are classified in ci-matrix.py so this PR and every future re-pin cost no device builds. Without that a blob update is a 107-device run. * ci: discover shadowed files instead of listing them by hand Qodo caught the shadow list omitting the device-local t21 and t31 kernel configs. It was right, and the hole was much bigger than the five it named: a hand-written list of 13 board configs against 93 same-path shadows covering 35 firmware paths. The missing ones are not incidental -- load_goke, load_hisilicon, load_sigmastar and four vendor .mk files are all shadowed by some device, and those are exactly the shared files a fleet-wide fix lands in. firmware regression-tests load_hisilicon's os_mem_size derivation; two devices here ship their own copy of that script and would not have seen the fix. Listing them by hand was the wrong shape. builder.sh copies devices/<item>/* over the firmware clone, so any file at a path firmware also has replaces it -- which makes same-path shadows discoverable rather than something to remember. discover_shadows() walks devices/ and reports anything sitting on a firmware path with no entry in firmware-drift.json, so the list cannot silently rot and a device added tomorrow cannot quietly introduce an unreconciled shadow. The manifest goes from 13 entries to 101: the 88 discovered ones, plus the 13 hand-authored entries that discovery cannot find because the name differs from the file they replace -- gk7205v200.generic-fpv shadows gk7205v200.generic, and nothing can infer that. Two self-test cases for the new path: a same-path shadow with no entry is reported, and an entry silences it. Verified against the tree by dropping the load_hisilicon entries, which surfaces both devices immediately. |
||
|
|
a0418c2987 |
kernel: drop CONFIG_VT from the device configs that shadow firmware's (#126)
builder.sh copies devices/<item>/* over the firmware checkout before make, so a device directory that carries its own board .config replaces firmware's copy outright. OpenIPC/firmware #2308 and #2309 turned CONFIG_VT and CONFIG_INPUT off across the fleet; the 13 board configs here were never touched by that, so 21 device builds carried on shipping the virtual-terminal layer -- /dev/tty0, /dev/tty1..63, the keyboard translation tables, console selection and screen code -- for a monitor and keyboard no camera has. flyrouter pointed this gap out on #2308. The transformation is not re-derived here. For each file the symbol-level delta was taken straight out of firmware's history (85233f0e^..HEAD) for the config it shadows and replayed, so these land on exactly the state that was reviewed and proven on hardware there. Every affected symbol in every copy still held firmware's pre-sweep value, so nothing here was a deliberate customisation -- they were simply stale. Eleven of the thirteen also needed CONFIG_EXPERT=y first. In drivers/tty/Kconfig the symbol reads config VT bool "Virtual terminal" if EXPERT select INPUT default y so its prompt exists only under EXPERT, and without it olddefconfig finds the symbol invisible and forces it back to its default -- "# CONFIG_VT is not set" on its own does nothing. Two exceptions: * gk7102c keeps CONFIG_INPUT. It sets CONFIG_INPUT_EVDEV=y and firmware's gk710x, which it shadows, keeps INPUT for the same reason. Only VT moves. * CONFIG_INPUT_LEDS=m is dropped on the six FPV/OTG copies. It is the input-to-LED bridge, lives inside `if INPUT`, and firmware never carried it, so olddefconfig would have dropped it silently -- stated here so the file matches the kernel it generates. CONFIG_LEDS_CLASS is a separate symbol in drivers/leds and is untouched: the FPV status LEDs are unaffected. Nothing consumes VT on any of these. FRAMEBUFFER_CONSOLE is its only in-kernel consumer and no config in this repository sets it at =y or =m, so the sole console driver compiled in was DUMMY_CONSOLE and writes to /dev/tty0 went nowhere. The ingenic t21/t31/t40 copies already matched firmware -- VT off, INPUT kept for their GPIO keys -- and are left alone. Verified by generating the kernel config the way builder.sh does: copy devices/common over a firmware checkout at master and run the configure step, before and after. gk7205v200_fpv, comparing the two generated build/linux-custom/.config files symbol by symbol: turned OFF (8) CONSOLE_TRANSLATIONS DUMMY_CONSOLE HW_CONSOLE INPUT INPUT_LEDS VT VT_CONSOLE VT_CONSOLE_SLEEP turned ON (1) EXPERT value changed none LEDS_CLASS=m, TTY, UNIX98_PTYS, SERIAL_AMBA_PL011_CONSOLE, USB_GADGET, CFG80211, MAC80211, KALLSYMS, COREDUMP, NAMESPACES, ELF_CORE, CORE_DUMP_DEFAULT_ELF_HEADERS, DEBUG_KERNEL, DEBUG_MEMORY_INIT: unchanged. That last line is the check #2308 missed on its first pass: EXPERT carries `select DEBUG_KERNEL` and unhides a block of on-by-default options, which there silently moved COREDUMP and friends. DEBUG_KERNEL was already y in these configs, so nothing else moved. Building the kernel both ways in that same tree, on the OpenIPC/linux goke tarball these devices use: gk7205v200_fpv uImage 2071368 -> 2036040 -35328 bytes (-1.71%) zImage 2058872 -> 2023544 -35328 bytes (-1.72%) which lines up with the -34680 bytes firmware measured on gk7205v200_lite for the same delta. drivers/input/input-leds.ko is built in the before tree and is not built after. |
||
|
|
7bfcab91ff |
ci: stop a NOT_BUILT device widening the matrix to all of them (#127)
NOT_BUILT is documented as the opt-out that narrows to nothing, and a change to
one of those devices' defconfigs does exactly that. Anything else in the same
directory did the opposite: targets_in() only ever returns devices CI builds, so
a directory holding nothing but opted-out devices came back empty and fell
through to the "is in no directory CI builds" widen. Touching a device CI
deliberately skips cost a full 107-device run.
$ echo devices/gk7205v200_rubyfpv_generic/br-ext-chip-goke/board/\
gk7205v200/gk7205v200.generic-fpv.config | python3 .github/scripts/ci-matrix.py --stdin
ci-matrix: 107/107 devices (needs_build=True) --- ... is in no directory CI builds
$ echo devices/gk7205v200_rubyfpv_generic/br-ext-chip-goke/configs/\
gk7205v200_rubyfpv_generic_defconfig | python3 .github/scripts/ci-matrix.py --stdin
ci-matrix: 0/107 devices (needs_build=False) --- nothing that reaches a build
Same device, same opt-out, opposite answers. #126 touches three NOT_BUILT
devices and is building all 107 because of it.
The empty result was carrying two meanings: "every device here is opted out" and
"this directory is not one I know". Only the second should widen. devices_in()
answers the second question -- it reads directory_of, which is built from every
defconfig in the tree rather than the built subset -- so an unrecognised
directory still widens, which is the half of the rule worth keeping.
Three self-test cases, one per meaning: a kernel config and an overlay file in a
NOT_BUILT device reach nothing, and a devices/ directory with no defconfig at
all still widens. With this, #126's own file list narrows from 107 to 23.
|
||
|
|
a5882d5e80 |
package: stop selecting jsonfilter, mirroring firmware #2304 (#128)
OpenIPC/firmware dropped BR2_PACKAGE_JSONFILTER from every one of its defconfigs in #2304, once the WebUI stopped calling it. builder's defconfigs are its own files, so 97 of them kept selecting it. jsonfilter selects JSON_C and LIBUBOX, and on a device that enables neither uqmi-openipc nor wifibroadcast-ng nothing else selects libubox, so it and jsonfilter shipped for nothing. That is what has had three devices over their rootfs cap: hi3518ev200_lite_switcam-hs303 rootfs 5124KB/5120KB -4KB ssc333_lite_babysense-see-hd-ip206 rootfs 5124KB/5120KB -4KB ssc333_lite_meari-speed-6s rootfs 5128KB/5120KB -8KB all three red on the nightly, meari since 2026-08-24. Bisecting meari across firmware revisions lands on #2301, which added 408 bytes to the comment-stripped sysupgrade script -- these images had no headroom left at all, and 408 bytes of a genuine bug fix was enough to push one over a 4KB padding step. The fix is to give them headroom, not to give back the bug fix. Measured on ssc333_lite_meari-speed-6s, built the way builder.sh builds it -- devices/<item>/ copied over a firmware checkout at master, clean tree both times: before rootfs.squashfs 5128KB/5120KB size exceeded by: 8KB after rootfs.squashfs 5096KB/5120KB 24KB spare -32KB, from /usr/bin/jsonfilter (18068 raw) and /usr/lib/libubox.so (30404 raw). json-c does NOT go: majestic lists it in MAJESTIC_DEPENDENCIES, so buildroot builds and installs it whether or not BR2_PACKAGE_JSON_C is set. Only the two files above leave the image. Two consumers genuinely need jsonfilter and both keep it: * devices/apfpv's own etc/init.d/S99msposd reads majestic's config.json through it, and ssc338q_apfpv and ssc378qe_apfpv do not enable wifibroadcast-ng. Those two keep the symbol, with the reason written above the line -- the same undeclared-runtime-dependency trap firmware #2305 had to fix, and the reason this is 95 defconfigs and not 97. * every other FPV device enables wifibroadcast-ng, whose Config.in selects BR2_PACKAGE_JSONFILTER (added by #2305) for the same script. They keep it without saying so. LTE devices keep libubox through uqmi-openipc, which selects it independently. Nothing else in this repository calls jsonfilter: grepping devices/ and package/ finds only that one S99msposd line, and firmware's own tree has no caller left outside wifibroadcast-ng. |
||
|
|
6fcd657a00 |
ci: publish the devices that did build when the matrix goes red (#125)
* ci: publish the devices that did build when the matrix goes red This morning's nightly built 97 of 98 devices. ssc333_lite_meari-speed-6s failed, and that one device cost every device its release: there is no nightly-20260824-* release, and `nightly` and `latest` still carry the 23rd's images. 2026-08-21 went the same way on two failures out of 98 -- no nightly-20260821-* either. The publish job is documented as best-effort -- "publish whatever the matrix produced even if some devices failed" -- and its condition already lists 'failure' as an accepted matrix result. It never got that far. A job whose `needs` failed is skipped by default, and an `if:` overrides that only when it CONTAINS a status function; reading needs.buildroot.result inside contains() does not count. So the job was skipped outright, never evaluated, and reported "skipped" rather than anything red. This has been true since #121 consolidated the release writes into a single writer to stop the concurrent-upload rate limits. That change was right -- before it each device uploaded from its own matrix job, so a failing device took down only itself. Both nightlies that have failed since then lost their whole release this way. `!cancelled()` rather than `always()`: the contains() already drops a cancelled or skipped matrix, but a run cancelled after a green matrix would still start uploading under always(), and a half-written nightly is what the single-writer design exists to avoid. The gate stays red on a partial matrix; that is unchanged. What changes is that a red run now still delivers the images it built. Devices that failed keep their previous image on nightly/latest, which the ci-gate already assumed; the new warning in Collect assets says so on the run rather than leaving it to be inferred. Same fix as OpenIPC/firmware#2303 -- the two publish jobs share a common ancestor and carried the identical gate. Verification: master.yml parses; lint-workflow-shell.py checks 23 run blocks clean (and its own self-test passes); ci-matrix.py --self-test ok. Publish condition audited against every path -- PR, no-op schedule, clone guard, cancelled run, failed select and all-devices-failed all still skip; only "matrix failed, some devices built" changes from skip to publish. * ci: finish the sentence in the partial-publish warning The line ended on "for every device that did not", leaving the reader to supply "build" from the clause before it. It is an operator-facing log line on the one run where somebody is trying to work out what shipped, so say it in full and point at where the failed devices are listed. builder has no Build summary job, so the run's own job list is that place. Raised by Qodo on #125. |