51723 Commits

Author SHA1 Message Date
Douglas Teles c9fa2ae9d3 archr: package scripts and alpm hooks so they ship through pacman
The archr scripts (archr-update, archr-flash-sync, archr-depmod,
wifictl, governors, ...) and the alpm hooks were installed in
post_install, which writes into the assembled image only, so they never
entered the pacman package: every one of them was flash-only. That is
why the dual update path could deliver package contents but not its own
plumbing, and the depmod fix would not have reached existing installs.
Move the copy into makeinstall_target so the package carries them and
pacman -Syu updates them like anything else.
v2.1.1
2026-07-08 21:37:13 -03:00
Douglas Teles faa9c6f6c4 update: stop the linux package from wiping out-of-tree modules
Installing the linux package through pacman overwrote modules.dep with
the copy generated at kernel build time, which predates every
out-of-tree module: the joypad and the WiFi drivers vanished from the
index and the console booted with dead input and no network
(reproduced on real hardware). Two independent layers fix it: the repo
generator no longer ships any depmod-generated index inside packages
(modules.builtin*/order stay, they are kernel-owned depmod inputs),
and a new alpm hook rebuilds the index over the full overlay tree
after any transaction that touches kernel modules. linux goes to rel 3
so updated devices pick the clean package.
2026-07-08 21:22:34 -03:00
Douglas Teles 14db5f1ffb archr-update: sanitize the channel and seed the pacman local db
Two failures kept every device from ever seeing an update. The ES
settings historically stored updates.branch=auto, which pointed the
mirrorlist at a repo tag that does not exist, so the metadata sync
always failed. And freshly flashed images carry an empty pacman local
database, so even with a working mirror there was nothing to compare
against and every check reported no updates. Fall back to stable for
unknown channels and seed the local db once from the published
archr-localdb tarball.

Known limitation of the remote seed: it reflects the newest repo
state, so the first check after seeding reports the current batch as
already installed. Baking the per-image database at build time is the
follow-up.
2026-07-08 18:28:41 -03:00
Douglas Teles b29af12832 RK3326: hold RTL8852AU out of the build, lwfinger tree breaks on 6.12
rtw_pwrctrl.c fails to compile against 6.12.94; the package stays in
the tree for a future port, and the common BU/CU variants remain in.
2026-07-08 18:00:14 -03:00
Douglas Teles 9723e3e09c packages: bump linux and kernel-firmware so MT7921U flows via pacman
The MT7921U enablement changes the kernel image and the firmware list;
without a REV bump pacman would never offer them and only reflashes
would pick the new driver up. The flash-sync hook then lands the new
kernel on the boot partition.
2026-07-08 17:55:15 -03:00
Douglas Teles c1b9f27838 RK3326: add out-of-tree drivers for the RTL8852 USB WiFi 6 family
The four-distro dongle census left the RTL8852AU/BU/CU chips as the
remaining orphans: common WiFi 6 dongles with no mainline USB support
on 6.12 (the in-kernel rtw89 only starts covering them in 6.17).
Package the maintained vendor drivers (morrownr for BU and CU, both
declaring kernels 5.15 to 6.14; lwfinger for AU, with version guards
up to 6.9 and strscpy fallbacks in place) pinned to current HEADs,
modeled on the sibling morrownr packages. No udev hand-off rules: the
USB IDs bind by modalias since nothing else claims them. RTL8831 and
AIC8800 stay untouched; they serve validated hardware.
2026-07-08 17:53:51 -03:00
Douglas Teles 2d04170214 RK3326: enable the in-tree MT7921U driver with its firmware
Common WiFi 6 dongles use the MediaTek MT7921U, which mainline has
supported since 5.18, but the kernel config never enabled the USB
glue and the firmware list did not ship the MT7961 blobs. Cheapest
gap found in the four-distro dongle driver census.
2026-07-08 17:44:08 -03:00
Douglas Teles 01bfa9a5c7 readme: reposition the project as an Arch Linux distribution
Arch R stopped being a ROCKNIX fork a long time ago: the OS is Arch
Linux ARM with pacman and the built-in updater (SteamOS-like model),
and only the image build tooling descends from the LibreELEC family
through JELOS/ROCKNIX. Refresh the outdated claims along the way: the
GPU stack ships libmali (Panfrost is not exposed), images are gzip not
xz, the board table now matches config.xml, DDR trains at 666MHz, and
the update, sleep and power LED features from 2.1 are documented.
2026-07-07 22:20:54 -03:00
Douglas Teles 8275879350 gen-pacman-repo: create the seed root before invoking pacman
pacman resolves the --root path before doing any work and errors out
when it does not exist, so the seed always failed after the cleanup rm.
2026-07-07 22:03:09 -03:00
Douglas Teles ccb3eaaa86 gen-pacman-repo: seed the local db with an aarch64 no-sig config
The host pacman applies the host architecture and signature policy to
the seed transaction, so every aarch64 package was rejected and the
local-db tarball was silently skipped, leaving freshly flashed images
without an upgradable base.
2026-07-07 22:01:20 -03:00
Douglas Teles 330c4199a6 packages: give quirks, sleep and system-utils a real version
Empty PKG_VERSION made gen-pacman-repo fall back to a garbage version
derived from the install dirname (quirks--quirks.-1) and broke the
package.mk lookup, so the PKG_REV bump was never honoured and pacman
could not see these packages as upgradable. Version them 2.1; vercmp
ranks it above the old garbage string, so 2.0 installs upgrade cleanly.
2026-07-07 21:59:07 -03:00
Douglas Teles 8b0f09c43e flash-sync: update only DTBs the image already ships
The per-image DTB set is curated by config.xml (the clone image carries
boards the original image deliberately leaves out), so the sync must
never add files to /flash/dtbs, only refresh the ones present. Caught
on the first hardware run: a clean sync on the original image added
three clone-only DTBs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v2.1
2026-07-07 20:59:57 -03:00
Douglas Teles 6faa39c570 update: let kernel and DTB fixes flow through pacman via flash-sync
Until now anything living on the FAT boot partition (kernel Image and
the device trees) was reflash-only, breaking the promise that every
update can arrive either by rewriting the image or through pacman and
the ES update menu. Close the gap with three pieces:

- The linux package now ships the kernel image in the rootfs under
  /usr/share/bootloader/Image next to the device_trees it already
  installs, so a pacman upgrade of linux delivers both.
- archr-flash-sync copies Image to /flash/KERNEL (refreshing the
  KERNEL.md5 sidecar) and device_trees/*.dtb to /flash/dtbs, but only
  the files whose sha256 actually changed, each written as a verified
  .new temp in the same FAT directory and renamed over the original so
  the torn-write window is the rename alone. /flash/overlays (the
  user's panel overlay), extlinux, boot scripts and u-boot are never
  touched; u-boot/TPL live in raw sectors where a torn write bricks
  the card, so the bootloader intentionally stays image-flash only.
- An alpm PostTransaction hook (HookDir /etc/pacman.d/hooks) fires the
  sync whenever a transaction touches the bootloader payload.

gen-pacman-repo now prunes the .image build-plumbing directory from
packages, which would otherwise dump a duplicate raw kernel at /.image
on every update.

Hardware test pending: run archr-flash-sync by hand over SSH and check
the device still boots with the synced KERNEL and dtbs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:10:49 -03:00
Douglas Teles 56cd1626d6 packages: bump PKG_REV so today's fixes flow through pacman updates
These packages have empty or upstream-pinned PKG_VERSION, so without a
PKG_REV bump pacman never sees the new build as an update and the fixes
would only reach users through a reflash. Covers headphone_sense and
input.service (system-utils), the LED and audio quirks (quirks), the
s2idle defaults (sleep), the Soysauce SDL mapping (gamecontrollerdb)
and the rewritten udev swap rule (RTL8188EUS).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 19:46:39 -03:00
Douglas Teles f99aff1149 RK3326: route the Soysauce PMIC interrupt to GPIO0_A7
Live debugging showed the whole rk817 interrupt line dead on the
Soysauce (zero counts in /proc/interrupts for pwrkey, jack and charger
events across button presses). The vendor DTB wires pmic_int to
GPIO0_A7 while the shared r3xs.dtsi listens on GPIO0_B2, so every PMIC
interrupt was lost: power key, headphone detect, charger plug and the
suspend wake source. Override the interrupt and the pinctrl in the
soysauce DTS only; the other family members really use GPIO0_B2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 19:29:51 -03:00
Douglas Teles 5f1f6182cf fake-suspend: cut the panel backlight even when DPMS handles the blank
The compositor path blanked the framebuffer but could leave the panel
backlight powered, so the "sleeping" console showed a black yet lit
screen and kept burning the display power budget. Turn the backlight
off through bl_power in both paths and restore it on wake.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 19:24:07 -03:00
Douglas Teles a0a45889f4 system-utils: enable input.service on RK3326
The whole power-button fake-suspend chain was dead code: input.service
(input_sense) is the only thing that turns KEY_POWER presses into
archr-fake-suspend calls, the R33S and RG351 dpad-volbright quirks even
restart it when active, but no package ever enabled it, so the power
key fell through to logind's kernel suspend, which locks up on px30.
Enable it for RK3326. Hardware test note: input_sense also reacts to
KEY_VOLUME events, so watch for double-stepping volume on the rocker;
if it doubles, the second handler needs to yield.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 19:23:05 -03:00
Douglas Teles 34b76db065 RK3326: default to fake-suspend, kernel suspend proven unwakeable
Hardware test on the Soysauce (2026-07-07) killed both kernel suspend
paths: SuspendState=mem hangs on entry and freeze (s2idle) enters but
never wakes, not even from an armed RTC alarm with every wakeup source
enabled (PMIC pwrkey, rk817 i2c and rtc0 all report enabled). Real
debugging needs UART on the pads.

Make the power button useful instead of a lockup: ship the RK3326
sleep.conf with AllowSuspend=no so logind's HandlePowerKey=suspend
becomes a no-op, and seed system.suspendmode=off through a platform
030-suspend_mode quirk so the archr-fake-suspend path (already wired
to the power key via input_sense) stops exiting early. The quirk also
serves the "default" choice of the ES SUSPEND MODE menu, and on boot
it repairs pacman-upgraded installs whose storage still carries the
old mem-first sleep.conf. Users can still opt in to real suspend
through the same menu (the suspendmode script rewrites the conf with
AllowSuspend=yes), and the sleep.sh state-preservation hooks stay in
place for the day s2idle works.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 19:20:16 -03:00
Douglas Teles 62edc065ad inputs: single source of truth for the built-in gamepad configs
Every platform pad needed three hand-maintained files (es_input.cfg,
the RetroArch autoconfig and gamecontrollerdb.txt) and nothing checked
they agreed; the Soysauce pad shipped without the SDL entry, so ports
saw no controller. Add projects/ArchR/inputs: one JSON definition per
pad plus gen-input-configs, which verifies the three artifacts against
the defs (wired as a fail-fast gate on the docker-% Makefile targets),
regenerates them on demand, imports legacy entries, and computes SDL
GUIDs the same way the runtime does, including the name-embedded form
SDL uses when vendor*product is zero.

The 17 platform pads were imported from the current artifacts and the
migration already caught two real inconsistencies. The GO-Super
gamecontrollerdb line carried a numeric-form GUID, but the pad reports
vendor 0 so SDL derives the name-embedded GUID at runtime (the form the
device-captured es_input block always had); the line is now fixed to
1900bb3e474f2d537570657220476100 and its RetroArch cfg canonicalized.
And retrogame_joypad legitimately ships different mappings per bus
(guide:b10 only on 0x19), now modeled explicitly as a per-GUID map.

Verification is semantic for es_input blocks and RetroArch cfgs (the
legacy files mix tabs and spaces) and byte-exact for gamecontrollerdb
lines, with GUIDs always recomputed from the identity fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 18:31:41 -03:00
Douglas Teles 205c5bccb3 sleep: default RK3326 to s2idle, preserve ALSA and governor state
Suspend on the R36S family hangs because the shipped sleep.conf orders
SuspendState as "mem standby freeze" and px30 mainline has no working
S3, so the kernel commits to a state it cannot leave. Ship
SuspendState=freeze on RK3326; the power button is the rk817 PMIC
pwrkey, which every board DTS already marks wakeup-source, and logind
already routes HandlePowerKey=suspend through systemd-sleep into this
hook.

Borrow the state discipline from the dArkOS sleep hooks: blank the
backlight before the kernel path runs, snapshot the full mixer state
with alsactl (the rk817 can lose its routing across s2idle and the
existing restore only re-set the master volume), and save/restore the
cpu/gpu/dmc governors. dwc2 reload on resume was already covered by
modules.bad.

Untested on hardware: needs a device check that s2idle enters (screen
and audio off), the pwrkey wakes it, and audio routing plus USB gadget
survive the round trip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 18:28:53 -03:00
Douglas Teles 8aacf5c823 headphone_sense: sync the startup path with the real jack switch state
The boot-time probe read a legacy /sys/class/gpio number that mainline
kernels never expose, so the initial audio path was always the speaker
guess and a reboot with headphones plugged started routed wrong. Query
the actual EV_SW/SW_HEADPHONE_INSERT bit through evtest --query (exit
10 = bit set; on these boards the switch is inverted, value 0 means
inserted) with the legacy gpio node as fallback, make an empty "$2"
follow the detected state instead of forcing speakers, and bail out
before the event loop when the board has no jack input device at all
(evtest on an empty path just dies and burns service restarts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 18:27:14 -03:00
Douglas Teles bd6fb8d0a9 gamecontrollerdb: add the Soysauce GO-Super Gamepad SDL mapping
SDL-based games and ports never recognized the Soysauce pad because
gamecontrollerdb.txt only knew r36s_Gamepad; RetroArch and ES have
their own configs, which is why "some games" needed manual input setup
(Reddit report on the 2.0 thread). GUID derived the same way SDL does:
bus 0x19 (host), crc16 of the device name (verified against the
r36s_Gamepad entry), vendor 0, product 0x1100, version 0x0100 from the
DTS; the button/axis layout matches the r36s entry, which is the same
physical layout the validated RetroArch config already uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 17:30:48 -03:00
Douglas Teles 0be7aab31b emulationstation: default power LED selection to on, matching boot
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 17:03:08 -03:00
Douglas Teles df92325273 RK3326: fix the shipped-but-broken v2.0 fixes for issues #19 and #35
Issue #19 (RTL8188EUS dongle can scan but never authenticates): the
udev swap rule shipped in v2.0 was structurally a no-op. It matched
the usb_device add event and echoed the device name ("1-1") into
rtl8xxxu's unbind node, but USB drivers bind to the interface
("1-1:1.0"), and at usb_device add time nothing is bound yet anyway;
the follow-up modprobe never rebinds an interface the in-tree driver
already claimed. Users confirmed the auth failure survived into the
release. Rewrite the rule to match the usb_interface event, where the
kernel has already finished its synchronous bind, and deterministically
move the interface: unbind from rtl8xxxu (no-op if it lost the probe
race) and write it into 8188eu's bind node via udev's own %k
substitution (no shell $$ escaping to get wrong).

Issue #35 (R36S Clone V20 speaker silent, headphones fine): the V20-era
clone boards route the speaker through the external amplifier exactly
like the Soysauce (the eeclone DTS already ships rk817-sound-amplified)
but the R36S Clone quirk never exported the playback mux paths nor the
jack input device. Reporters on the issue validated this exact config
by hand-editing the quirk. Also fix headphone_sense: every amixer cset
passed the control name unquoted, so names with spaces ("Playback Mux")
split into two arguments and the call failed; and the boot-time jack
probe read a legacy /sys/class/gpio node that mainline kernels don't
expose, now guarded with a speaker-path default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 16:18:39 -03:00
Douglas Teles 4385a37cbf RK3326: fix Soysauce power LED polarity, surface DISABLE POWER LED
Live debugging on the Soysauce (USB SSH, watcher on the led sysfs while
the user drove the ES menu) showed the whole chain working but the LED
responding inverted: the blue power LED is wired active high, so the
GPIO_ACTIVE_LOW in the DTS made "off" light it and "on" darken it
(heartbeat looked normal because a blink is a blink upside down). Flip
the polarity and default the LED on so early boot keeps the stock look.
The led-red node was a phantom: the physical red LED belongs to the
charger IC and toggling GPIO0_A5 changes nothing, so drop it.

The DISABLE POWER LED switch in ES is gated on DEVICE_PWR_LED_CONTROL,
which sits in the 999-export allowlist but was never set by any quirk,
so the item was invisible on every device. Set it for the R36S family.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 15:42:40 -03:00