The osdrv packages create default.ini as a symlink to one fixed sensor's
IQ file -- imx307.ini for hisilicon-osdrv-hi3516ev200 and
goke-osdrv-gk7205v200. Two device profiles prune that exact file to fit
NOR and leave the symlink behind, so the image ships a default.ini that
resolves to nothing.
majestic answers that silently. init_iq_monitor() (src/hisi/sdk.c) has no
default for isp.iqProfile, falls through to /etc/sensors/iq/default.ini,
and returns on `access(default_prof, 0) != 0` without logging at any
level. No IQ profile means no monitor thread, so SCENE_Set3DNR() never
runs and VPSS keeps the single static NRX block from scene.c tune_vpss()
at every ISO. The explicit-iqProfile path does log "Cannot find %s file";
only this fallback is mute.
Measured on a lab hi3516ev300_85h50ai (IMX335, nightly-20260904-605fa9d)
against a night scene at ISO ~30000, changing nothing but the profile
majestic loads:
dangling imx335.ini
RTSP, 20 s capture 14.13 Mbit/s 3.54 Mbit/s
/proc/umap/rc InsBr 14310 kbps 3626 kbps
StartQp 42 (= MaxQp) 31
3DNR SFS2 5/16/0/30 36/60/60/52
3DNR TFS 1/7/12/10 5/9/13/11
The encoder was configured correctly the whole time -- VBR 4096, MinQp
28, MaxQp 42. Rate control pinned at MaxQp while still emitting 14 Mbit/s
is what an undenoised sensor at ISO 30000 costs, not a bitrate that was
ignored. It reads as "the bitrate setting does nothing" and "3DNR is
off", which is how it was reported.
hi3516ev300_lite_xm-85h50ai keeps imx335.ini and runs an IMX335, so
general/overlay now carries a default.ini aimed at it. BR2_ROOTFS_OVERLAY
is rsynced after the packages install and rootfs_script.sh runs the
excludes list after that, so the overlay's symlink replaces the package's
and the pruning that follows is harmless. This also stops the board
loading an IMX307 profile for an IMX335 sensor, which is what it would
have got had imx307.ini simply been kept.
gk7202v300_lite_ipg-g3-wr prunes every IQ file its package installs
(imx307, imx335, sc2232), so there is nothing to aim a symlink at. It
drops default.ini instead. Behaviour is unchanged -- majestic already
loads no profile there -- but the image stops carrying a broken link that
would silently start resolving to the wrong sensor's profile the moment
one of those entries goes stale. The board runs jxh63, which no shipped
IQ file covers; a note in the list records that keeping imx307.ini costs
126 KB if it turns out to want one.
An audit of every device profile against its SoC's osdrv package finds no
others: the rest either keep the symlink's target, remove default.ini
already, or pin .isp.iqProfile in customizer.sh.
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.
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.
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.
* ci: check the setting paths shipped scripts hand to cli
`cli -s` cannot fail. yaml-cli stores whatever dotted path it is given,
creating intermediate mappings as it goes, and exits 0; majestic then silently
ignores a key it does not recognise. So a typo in a setting path applies
nothing and reports nothing, from the moment it is written to the end of the
device's life.
t40_lite_movols-mo-805p has been shipping six of them:
cli -s .video0.bitrate: 4000
cli -s .video0.rcMode: avbr
The path is `.video0.bitrate:`, not `.video0.bitrate`. Bitrate, rate-control
mode, profile, GOP size, GOP mode and OSD size have never applied on that
camera. The trailing colons are dropped here, including the one on the
commented-out `.onvif.enabled:`, which was a trap for whoever uncommented it.
The linter checks shape and nothing else. Whether a well-formed key is one a
given majestic build actually declares can only be answered by the running
binary -- it varies by vendor and by flavour -- while shape is decidable from
the tree, costs nothing, and is the whole of the class that shipped. A path
built at runtime is skipped rather than guessed at: uvc-gadget-setup reads
`cli -g ".$1"`, which is fine and unknowable here.
It carries a floor check for the same reason lint-workflow-shell.py does. A
matcher that quietly stops matching finds no bad paths, which looks exactly
like a clean tree -- so finding no cli invocation at all is itself a failure.
80 scripts scanned, 610 invocations, 6 bad paths, all in the one device.
* ci: recheck the merged result when the cli linter itself changes
lint.yml's push trigger names the checkers it guards one by one, and the new
one was not on the list -- so a master push touching only
.github/scripts/lint-cli-paths.py would have skipped the very job that exists
because #121 shipped a broken merged result nothing re-checked.
Same reasoning as the lint-workflow-shell.py entry beside it, and the same
cost: seconds, no runners.
Select BR2_PACKAGE_MAJESTIC_AF in the device defconfig so the test board's firmware carries /usr/lib/majestic-af.so out of the box. The package is defined in the firmware external tree (OpenIPC/firmware#2357, merged first); builder.sh clones firmware master, and the device build compiles the plugin from source (7caebdc6) and installs it — verified end-to-end in CI after the firmware merge.
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.
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.
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.
This overlay carried a 25KB sensor_imx335_mipi.ko because the driver OpenIPC
built at the time could not reach the rates this board needs: its 2560x1920@60
mode served 30fps and its 90fps mode produced no usable output at all. The blob
shadowed the built module and fixed it for this one device, and for nobody else.
The source behind it is now what OpenIPC builds. openipc/sensors carries it as
sigmastar/infinity6c/sensor_imx335_mipi.c instead of a symlink to the infinity6e
driver (OpenIPC/sensors#3), and the infinity6c loader states the lane count it
needs (OpenIPC/firmware#2343). sigmastar-osdrv-sensors is unpinned, and this
device's defconfig already selects it -- BR2_PACKAGE_SIGMASTAR_OSDRV_INFINITY6C
selects BR2_PACKAGE_SIGMASTAR_OSDRV_SENSORS -- so the module is built and
installed to /lib/modules/5.10.61/sigmastar either way. The overlay copy was
only ever shadowing it.
Removing it means this device tracks the driver instead of freezing a copy of
it, which is the point: the next person who needs a mode changed can change it.
The built driver is a later revision than the blob (72ad30b against the
30fdac4 it came from) and measures the same or better on an SSC377QE, rebooting
before every mode:
2592x1944@59 59.2 fps (blob 59.2)
2560x1920@60 60.1 fps (blob 58.4)
2208x1248@90 89.5 fps (blob 89.5)
1920x1080@120 116.1 fps (blob 119.6)
Verified end to end on hardware afterwards: with the built module and the
merged loader and nothing else, the loader applies lane_num=4 on its own and a
60fps request delivers 60.0.
Nothing else in the overlay changes.
GK-W7 board (product string ipc533331a-W7-gc2053dvp-f8): GK7202V300, 8MB NOR,
GC2053 wired in DVP/parallel mode with the SID strap high, iComm/SSV SSV6006C USB
WiFi (8065:6000), no Ethernet PHY.
Differs from the generic gk7202v300_lite target in two ways it cannot express
without a profile. The sensor is on the DVP pads, so open_sys_config's MIPI
arguments mux i2c to pads nothing is connected to and no sensor is ever detected;
customizer.sh opts into the sensor_dvp / sensor_mclk gate added in
OpenIPC/firmware#2276. And the Lite target ships only mt7601u, which will never
bind an SSV part, so the defconfig selects BR2_PACKAGE_SSV635X_OPENIPC and the
overlay adds the ssv6x5x-generic wlandev branch.
Named generic-w7 rather than after a vendor: the board carries no identifiable
vendor marking, and "gk" is Goke -- the SoC vendor, already encoded in the soc
field -- not the board's. `generic` is the established token here
(gk7205v200_otg_generic, ssc30kq_rubyfpv_generic).
Verified: builds green, rootfs 5017600B with 220KB of headroom in the 5120KB
partition; the baked load_goke is master's verbatim (md5 confirmed after
normalising the build's comment stripping); customizer.sh carries both env vars
and is sh/dash/ash clean; S30customizer runs it on first boot ahead of S70vendor,
so the vars are set before load_goke reads them; and on hardware, master's
load_goke driven only by those two vars brings up the DVP GC2053 at 1920x1080
@ 25 fps with i2c init failures 0 and ISP errors 0.
Not verified: the conjunction of the above on a single unattended first boot from
this image with no hand-set environment. Each link is independently evidenced;
the composition is not. Follow-up expected on the PR.
Headroom note for later: 220KB of rootfs headroom is about 4% of the partition,
and this family has a history of profiles going over as majestic grows.
gk7202v300_lite.list is the lever.
Refs: OpenIPC/firmware#2074, OpenIPC/firmware#2276
Two changes for the TP-Link Kasa KC110, both device-local.
BR2_OPENIPC_MAJESTIC="ultimate" brings the defconfig in line with the only other devices
that set it, hi3516ev300_ultimate_rostelecom-ipc8232swc-we and
hi3516ev300_ultimate_rvi-1ncmw2028.
The overlay ships a vendor libsns_ov2735.so, which fixes the no-video symptom on this
board. hisilicon-osdrv-hi3516cv200 already installs a libsns_ov2735.so of its own, so
this overrides it rather than filling a gap; the two are different builds (23076 bytes
here against 17988 upstream), consistent with the KC110 needing the MIPI variant while
the osdrv ships the DVP/i2c one. That matches the ov2735_mipi_1080p.ini and the patched
load_hisilicon this device already carried.
Verified in CI against master (run 33106540798, merge dc5c2fc):
ci-matrix: 1/110 devices (needs_build=True) --- narrowed to the affected devices
Firmware (hi3518ev200_ultimate_tplink-kasa-kc110) SUCCESS
- uImage: [1776KB/2048KB]
- rootfs.squashfs: [6276KB/8192KB]
No entry in hi3518ev200_ultimate.list reported "matched no file", so the prune list is
not stale against the overlay, and /usr/lib/sensors/libsns_ov2735.so is not one of the
paths it strips -- the blob reaches the image.
This device only started building at all in #132, which took it out of the NOT_BUILT
opt-out in ci-matrix.py; the CI-registration half of this PR landed there.
#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.
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.
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.
Booting the otg profile with /etc/usbmode = device made S72usbmode's
`usb-mode device` log, on every single boot:
xhci-hcd xhci-hcd.0.auto: Host not halted after 16000 microseconds.
xhci-hcd xhci-hcd.0.auto: Host controller not halted, aborting reset.
dwc3_core_init() leaves GCTL.PRTCAPDIR = OTG(3) and this 4.9 dwc3 never
moves off OTG on its own. xhci-hcd binds and registers both buses on top
of that anyway, but it is not actually driving the port -- so unbinding
straight from OTG asks xhci_halt() to halt a host that was never really
running, and it times out.
The gadget composed regardless, so this was cosmetic in practice, but it
left the host controller un-halted: exactly the live-DMA-engine state the
unbind is there to avoid.
Flip the controller to host before unbinding, so the already-bound xHCI
is genuinely running and the unbind halts cleanly. A switch from host is
already in that state, so only boot pays for the extra flip.
Measured on gk7205v200 (Xiongmai IPC_GK7205V200_50H20AI_S38): 5/5 cold
boots warned before, 0/5 after. Runtime host<->device round trips stay
clean and still take ~0.35s, with no reboot and no majestic restart.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds gk7205v200_otg_generic, a firmware profile that puts the single DWC3
controller into dual-role so the board can either consume a USB webcam
(existing usbcam path, host role) or present itself to a PC as one (UVC
gadget, device role). The roles are mutually exclusive -- xHCI HCSPARAMS1
reports MaxPorts = 1 -- but usb-mode switches between them at runtime, so
one image covers both and no reboot is needed.
Kernel side, three patches:
0015 sets dr_mode = "otg" in the DTS so dwc3 registers both an xHCI host
and a UDC.
0016 makes device mode actually work on a part that has only ever run as
a host. Three fixes: re-run dwc3_event_buffers_setup() on gadget start
(an xHCI reset wipes GEVNTADR), soft-reset the core before taking the
lock so the PHY is re-initialised (without it high-speed chirp fails),
and swallow the run_stop timeout on pullup(0), which otherwise
permanently poisons cdev->deactivations.
0017 disables the vendor's UVC_SG_REQ path. It hands a whole frame to the
UDC as one scatter-gather request; dwc3 chains those sg entries into a
single isochronous service interval, which on a full-speed link is one
1023-byte packet, so every frame larger than that reached the host
truncated and H.264 decoders reported "bytestream -5" on roughly half the
frames. Goke never shipped this path enabled -- CONFIG_USB_CONFIGFS_F_UVC
is unset in every vendor defconfig, including gk7605v100's, and the SDK
carries no userspace UVC sample -- so it was never exercised. The
mainline path (32 plain one-packet requests) is used instead.
Userspace side: usb-mode switches roles with the unbind/flip/bind
sequencing dwc3_set_mode() does not do on its own, uvc-gadget-setup
composes the configfs gadget, and S72usbmode forces a concrete role at
boot -- not optional, since dr_mode = "otg" leaves GCTL.PRTCAPDIR in a
state this 4.9 dwc3 never moves off by itself.
The descriptors advertise exactly the one format, frame size and interval
majestic is configured to serve, read from /etc/majestic.yaml. majestic
answers every PROBE/COMMIT with its own bFormatIndex/bFrameIndex because
it has one stream and cannot follow the host, so anything extra is an
invitation to select something that will not arrive: asking for MJPEG got
raw H.264 (an SPS where a JPEG SOI belongs, garbage to every consumer),
and asking for 1080p got 720p.
Profile drops the air-unit packages (wifibroadcast, rtl8812au, mavfwd,
mavlink-router, vtund, linux-firmware, wireless-tools) and the whole
wireless kernel stack, which pays for usb_f_uvc.ko and for keeping the
full sensor list -- the fpv trim to IMX307/IMX335 is keyed on
OPENIPC_VARIANT="fpv", and a general-purpose USB webcam should not be
sensor-locked.
Measured on a gk7205v200 lab board over a full-speed link: H.264
1280x720 at 30 fps with zero decoder errors and no dropped buffers, and
MJPEG delivering valid JPEGs at the jpeg channel's own rate.
Requires a majestic built with ENABLE_UVC_GADGET to feed the gadget;
that is a separate change.
Enable the media / V4L2 / uvcvideo kernel stack so a USB camera exposes
/dev/videoN for majestic's usbcam second-camera path.
To fit the 8M NOR (2M kernel / 5M rootfs) without dropping any sensor
library, uvcvideo and the videobuf2 framework are built INTO the kernel
(=y) instead of shipped as rootfs modules: the kernel partition had ~55 KB
of spare room while the rootfs was tight, so ~44 KB of weight moves from
rootfs to kernel. Resulting images: uImage 2022.8 KB / 2048 KB (25 KB
spare), rootfs squashfs 5080 KB / 5120 KB (40 KB spare).
GSPCA -- a separate driver for non-UVC webcams, pulled in by "default m
depends on VIDEO_V4L2" -- is disabled.
No kernel patch is carried: mmap capture works on stock uvcvideo once
majestic aligns its mmap() prototype with this MMAP_MUSL build's
uint32_t-offset shim (a userspace fix), so the earlier read()/fileio
uvcvideo patch is not needed.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Dahua-OEM 2 MP camera. The SC223A is on hardware I2C0 routed to the
VI-RAW pads (0x112c0060/0x64 func2) rather than the default mipi-sensor
pads (0x30/0x34 func1) the SDK probes, and needs a 27 MHz MCLK
(0x120100f0=0x19; SDK default 0x11/div4 leaves it unresponsive).
S71devmem re-muxes the pads, selects the SENSOR_RSTN reset (GPIO8_7
func2) and fixes MCLK after S70vendor/load_goke; the stock
open_sensor_i2c then reaches the sensor over /dev/i2c-0. No kernel
module needed.
Verified on hardware: chip-id 0xcb3e over HW I2C0, MIPI lock 1920x1080
zero errors, majestic streams correct colour 1080p.
Co-authored-by: build <build@local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Add TP-Link Kasa KC110 (HI3518EV200 + OV2735)
New device variant: hi3518ev200_ultimate_tplink-kasa-kc110.
Contents:
- kc110-board-support package: PTZ binary (mmap'd PL061), gpio-motors
shim for the openipc web GUI, IR control script, and a boot-time
pinmux init that writes 0x1 to the chip7/chip8 pads (0x200f00e8/ec/
f0/fc/100/104). The OpenIPC kernel pinctrl driver does not auto-set
these for the KC110's pan motor / IR-cut / IR-LED pads — the vendor
firmware writes them explicitly in hn_config.sh. Without this,
PL061 GPIODATA writes succeed silently but the pads never drive
the ULN2803 / solenoid / LED.
- Device overlay:
* etc/sensors/ov2735_i2c_1080p.ini — input_mode=0 (MIPI), 1-lane
(was input_mode=4 / 4-lane in upstream cv200 osdrv, which is
wrong for OV2735).
* usr/bin/load_hisilicon — adds an "ov2735" case that mirrors
ov2710_mipi (same MIPI pinmux + clock).
* usr/share/openipc/customizer.sh — first-boot configuration:
RTL8188FU wlandev, sensor config path, IR-cut pin 64, backlight
pin 63, lightMonitor true (AE recovery after IR-cut toggle).
- README.md row.
Hardware notes:
- SoC: Hi3518EV200; Sensor: OV2735 (MIPI 1-lane, RAW10);
Wi-Fi: RTL8188FU (USB); Flash: W25Q128 16 MB NOR.
- PTZ: 4-phase unipolar steppers via ULN2803 darlington array.
Pan = vendor base-10 GPIO 81/74/73/72 = OpenIPC PL061 65/60/59/58;
tilt = 0/1/2/44 = 0/1/2/36 (vendor's "44" is bank 4 pin 4 — i.e.
pin 36 in OpenIPC's PL061 numbering, NOT 44).
- IR-cut filter: GPIO 64 (vendor 80) active-low; IR-LED: GPIO 63
(vendor 77).
Status: PTZ + GPIO + IR fully functional. Video pipeline currently
needs an LD_PRELOAD shim around HI_MIPI_SET_DEV_ATTR because upstream
majestic builds combo_dev_attr_t with enIntfMode=DC / raw_data_type=0
for MIPI sensors that need RAW10. The shim is downstream-only pending
a real fix to majestic upstream; this PR delivers the rest of the
KC110 board support and will produce a fully-functional camera once
the majestic fix lands.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* tplink-kasa-kc110: use ov2735_mipi_1080p.ini
Follow OpenIPC/firmware #2155, which ships the OV2735 MIPI config as a
separate ov2735_mipi_1080p.ini and leaves ov2735_i2c_1080p.ini (the
parallel/DVP config) untouched.
- Rename the device's bundled sensor .ini to ov2735_mipi_1080p.ini and
carry the full corrected MIPI config: input_mode=0 (MIPI),
data_type=2 (RAW10), lane_id 2-lane, Input_mod=5 (MIPI),
Mask_0=0xFFF00000. The previous bundled copy only had input_mode
fixed (data_type/Input_mod/Mask_0 were still the wrong DVP defaults).
- Point customizer.sh's isp.sensorConfig at the new file.
- Exclude the unused parallel ov2735_i2c_1080p.ini from the image.
Verified on a TP-Link Kasa KC110 (OV2735 2-lane MIPI RAW10): clean
image, correct AE, RTSP H.264 1080p.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: moontwister <moontwister@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
OpenIPC/firmware PR #2162 (merged 2026-05-30) dropped the legacy
BR2_TOOLCHAIN_EXTERNAL_GCC_8=y + BR2_GCC_VERSION_LEGACY=y block from
its 18 ARM defconfigs and ships gcc 13.3.0 to those platforms now.
OpenIPC/builder's per-device and common Goke defconfigs still pinned
gcc 8, so every Goke job in the 2026-06-02 nightly Build run failed at
the toolchain stage with:
Incorrect selection of gcc version: expected 8.x, got 13.3.0
make[1]: *** [toolchain-external-custom/.stamp_configured] Error 1
Mirror #2162 across the 24 affected defconfigs (8 common + 16
per-device). No other defconfig content changes.
Unrelated 4 Sigmastar rootfs-overflow failures in the same nightly are
tracked separately.
Fixes failing run: https://github.com/OpenIPC/builder/actions/runs/26804792607
Co-authored-by: John <zekccsripfwrocp-15689@yn.furvionx.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
OpenIPC/firmware PR #2090 (2026-05-13, "IMX335 companion to
openhisilicon #99") renamed `general/package/goke-osdrv-gk7205v200/
files/sensor/config/60fps/` to `high-fps/`. The xg521 device-specific
goke-osdrv-gk7205v200.mk override here still references the old path,
causing every cron build of gk7202v300_lite_xg521 to fail:
/usr/bin/install: cannot stat 'general/package/goke-osdrv-gk7205v200//
files/sensor/config/60fps/*.ini': No such file or directory
Update the two install lines to use `high-fps` matching the renamed
upstream directory. Target install path also moves from
/etc/sensors/60fps → /etc/sensors/high-fps for consistency with what
the rest of the V4 sensor presets use.
The matching exclude-list entry in
devices/gk7202v300_lite_xg521/general/scripts/excludes/gk7202v300_lite.list
references /etc/sensors/60fps/... and is now stale; left as-is since
`rm -f` on a non-existent path is a no-op (rootfs_script.sh:
xargs -I % rm -f ${TARGET_DIR}%). Can be cleaned in a follow-up.
Other Goke device overlays (gk7205v200_lite_*, gk7205v210_lite_*,
gk7205v300_lite_*) only have the same exclude-list staleness and no
broken install rule, so they aren't affected by this bug.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add BR2_PACKAGE_HISILICON_OPENSDK=y to 9 hi3516cv200-family profiles
that were missing it. These boards will now get open_ modules built
from openhisilicon source instead of vendor-only blobs from osdrv.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>