-
Notifications
You must be signed in to change notification settings - Fork 1
H700 port 00 Device facts
Ground truth and probe notebook for the H700 platform. Current pass/fail results live
in 08; release decisions live in 09.
Everything here was verified live on hardware
over SSH (probed 2026-07-08, corrections folded in from the implementation/review
cycle through 2026-07-10) or recovered from git history. Re-run the probes after any
Anbernic stock-firmware update — paths have historically been stable, but the
dmenu_ln/muOS hooks are stockmod-version-dependent.
| Device | Evidence | Role |
|---|---|---|
| TrimUI Brick (TG5040, A133P) | Probed live | Reference — NextUI runs perfectly |
| Anbernic RG40XXV (H700) | Probed live | 640×480, one stick, HDMI; primary probe device |
| Anbernic RG34XXSP (H700) | User-tested | 720×480, dual sticks, clamshell lid sensor |
| Anbernic RG28XX (H700) | User-tested | Rotated 480×640 panel |
| Anbernic RG SP (H700) | Firmware-analysed | 720×480, no sticks; RG34XXSP hardware minus the sticks |
Established by comparing the stock 2026-07-27 ANBERNIC RG SP TF1.img against both
the RG34XXSP stock and StockMod images. The two devices are near-identical: same
DRAM type (boot0 differs by 11 bytes of parameter block), same kernel size to the
byte, and mali_kbase/8821cs/rtl_btlpm with byte-identical .text.
The entire device-tree difference is 34 lines:
| Change | Meaning |
|---|---|
lcd_* unchanged — lcd_driver_name = "rg34xxsp_v1", 720×480, identical timings |
same panel; DTB fingerprint 26-820-536, the 34xx entry in the panel-fix table below |
pmu_battery_cap 0xce4 → 0xdac
|
3300 → 3500 mAh |
keyL3/keyR3 removed; amux-en-gpios, A0_gpio, A1_gpio, adc-en-gpios removed |
no analog sticks |
GPADC status okay → disabled, five unused key0..4_vol/val added |
stick ADC turned off |
⚠ The stock bootlogo.bmp is 640×480 on a 720×480 panel — on the RG34XXSP too.
It is a stock packaging quirk, not evidence about the panel; StockMod replaces it
with a correct 720×480 image. Do not treat the vendor bootlogo as a geometry source.
- SoC: Allwinner H700, device-tree compatible:
allwinner,h616,arm,sun50iw9p1 -
/proc/device-tree/model:sun50iw9 - Kernel:
Linux ANBERNIC 4.9.170 #16 SMP PREEMPT aarch64(built 2026-05-21) - Userland: Ubuntu 22.04 (Jammy) arm64, glibc 2.35 — full apt-capable distro,
systemd, sshd out of the box.
/bin/shis dash, not bash — pak/launch scripts must be POSIX (&>silently backgrounds under dash; this broke game launch once). - RAM: 1 GB (
MemTotal: 996628 kB) - CPU: 4× Cortex-A53 (
CPU part 0xd03), cpufreq 480 MHz – 1.512 GHz, single cluster- governors:
interactive conservative ondemand userspace powersave performance schedutil - policy path:
/sys/devices/system/cpu/cpu0/cpufreq/
- governors:
- Thermal zones (
/sys/class/thermal/thermal_zone*/type): zone0=cpu, zone1=gpu, zone2=ve, zone3=ddr, zone4=battery (a first-draft platform.c read zone2 for GPU — wrong; it's the video engine)
-
/dev/fb0: 640×480 (virtual_size640,480); modes list includesU:1280x1024p-59,U:640x480p-75,U:640x480p-59(HDMI modes appear here) - Allwinner disp2 driver:
/dev/dispchar device present -
/sys/class/disp/disp/attr/contains:color_temperature,enhance_bright,enhance_contrast,enhance_saturation,enhance_mode,xres,yres, … — near-identical attribute set to TG5040 (same disp2 driver family). ⚠color_temperatureworks; theenhance_*attrs accept writes but have no visible effect on RG XX panels (unlike tg5040) -
No
/sys/class/backlight— brightness via/dev/dispioctlDISP_LCD_SET_BRIGHTNESS(0x102), args{0, raw 0-255, 0, 0}. Confirmed working in the shipped port (level curve in 03). There is also abrightnessfile under the AXP battery sysfs used by the stockbrightCtrl.bindaemon — we kill that daemon at launch. - Gamma LUT ioctls
DISP_LCD_SET_GAMMA_TABLE (0x10b)/GAMMA_CORRECTION_ENABLE (0x10c)/DISABLE (0x10d)— confirmed working: displaycal RGB gains visibly act, persist, and survive sleep + game launch on RG40XXV. - Boot arg:
lcd_type=boe(panel vendor in cmdline — may vary per unit) - HDMI hotplug:
/sys/class/extcon/hdmi/(extcon0);stateandcable.0/stateboth probed by the shippedGetHDMI().
- Mali-G31 MP2 ("bifrost"), kernel module
mali_kbaser20p0-01rel0 (UK 11.17),/dev/mali0 - Vendor blob: monolithic
/usr/lib/libmali.so.0.20.0(19 MB) — ELF 64-bit aarch64;libEGL.so.1.4.0/libGLESv2.so.2.1.0/libGLESv1_CM.soare 4 KB 64-bit shims over it - Blob version string:
OpenGL ES 3.2 v1.r20p0-01rel0— userspace r20p0 matches kernel kbase r20p0 ✔ - Blob EGL winsys = fbdev (
mali_egl_winsys_fbdev.cpaths in binary) — what the SDL mali-fbdev backend targets. Confirmed end-to-end: NextUI's full GLES 3 shader pipeline (shaders, overlays, effects) runs on it. - Stock
/usr/lib/libSDL2-2.0.so.0.12.0is 64-bit, built with only themali+dummyvideo drivers — the stock OS itself uses the SDL-on-mali-fbdev stack. -
Do not link GLES via the tg5040 SDK's
glesv2pkg-config — it drags in libUMP (Utgard-era, absent on Mali-G31 stock). Link-lGLESv2 -lEGLdirectly. - Mesa copies under
/usr/lib/aarch64-linux-gnu/are irrelevant on the 4.9 kernel (no DRM).
- ALSA cards:
0 audiocodec(speaker/lineout/headphone),1 ahubdam,2 ahubhdmi(HDMI audio) - amixer simple controls on card 0:
'digital volume','lineout volume','LINEOUT','SPK','OutputL/R Mixer DACL/R','tx hub mode' -
digital volumeis an attenuator with a reversed scale (range 0–63; larger raw value = quieter). The shipped msettings writes100 - valpercent — confirmed correct by listening on device. Volume control has no known issues on RG40XXV or RG34XXSP; the UI and audible levels are correct from mute through 100%. - Codec supports 48000/44100 natively.
-
Stock libasound quirk (critical): the device's
/usr/lib/libasound.soexports both versioned symbols and legacy unversionedALSA_0.9value-semanticsnd_pcm_hw_params_set_*symbols. A binary cross-built against a libasound without symbol versioning (the tg5040 SDK's) resolves the unversioned variants at load time →set_rate_nearbehaves like the 0.9 API and clamped the codec to 192 kHz while SDL believed 32.768 kHz → sliced/glitchy audio. Fix: build SDL2 with--enable-alsa-sharedso it dlopens the device libasound (dlsym picks the default/new-API symbols). See 05. - Headphone jack: the codec/hardware auto-mutes the speaker and routes audio without
NextUI. The old
snd_soc_sunxi_component_jack/parameters/jack_statesoftware path was historically always 0 and remains unused; see 05.
-
event0—axp2202-pek(power button, PMIC). KEY_POWER = 116. -
event1—ANBERNIC-keys(gpio-keys-polled): handlerskbd js0 event1- KEY bits: {1, 114, 115, 304–316, 354} — no d-pad keycodes; the d-pad is delivered as ABS_HAT0X/Y (the old port's UP 103 / DOWN 108 / LEFT 105 / RIGHT 106 codes do not appear on current firmware)
- ABS bits
0x3003c= ABS_Z, ABS_RX, ABS_RY, ABS_RZ (analog sticks; H700 scales the signed values by ×32767/4096) + ABS_HAT0X/Y (d-pad) - FF bits present (input-FF rumble is theoretically available; port uses
motosysfs instead)
-
event2—dierct-keys-polled(volume keys: PLUS 115, MINUS 114) -
/dev/input/js0exists. The in-tree SDL patch restores no-udev classification of the built-in pad, but the H700 platform deliberately skips it as an SDL joystick: raw evdev already supplies those events, and SDL's built-in ordering does not match the external-padJOY_*mapping. SDL joystick input remains enabled for external controllers (SDL_JOYSTICK_DISABLE_UDEV=1). - Verified evdev button codes (event1): A 304, B 305, Y 306, X 307, L1 308, R1 309, SELECT 310, START 311, MENU 312, L3 313, L2 314, R2 315, R3 316, PLUS 115, MINUS 114.
-
MENU emits a compound sequence on short taps (verified via evtest on RG34XXSP,
likely all RG XX H700 models): 312 down at press, 312 up at release, then a
synthetic 354 (
KEY_GOTO) down at the same instant as the 312 up, 354 up ~190 ms later. On a long hold, only 312 fires (down/up, no 354). So 312 tracks the physical button; 354 is a firmware "tap detected" pulse and must not be mapped to BTN_MENU — doing so extends every tap past the 250 ms long-press threshold (tap misread as hold → brightness overlay instead of shortcuts). The extra KEY_ESC (code 1) capability bit has not been observed to fire. - After the no-udev classification patch, SDL orders the built-in pad by evdev key
code: ESC/VOL−/VOL+ occupy indices 0–2 and the gamepad cluster starts at A=3
through MENU=11. This ordering is diagnostic only; the runtime skips this SDL
device and reads it through evdev. The
JOY_*constants inplatform.hdescribe the expected external-pad mapping, not the built-in pad. -
evtestis available on the device for mapping discovery.
-
/sys/power/state:freeze mem— real suspend-to-RAM (same as TG5040) -
echo memsuspend works; wake source is the power button (AXP2202 PEK). RTC alarm wake does NOT fire — no timed wake; don't build features on it. The shipped sleep/wake path is reliable in repeated RG40XXV/RG34XXSP testing, including in-game resume and power-off auto-resume. On RG34XXSP, POWER can wake light sleep while the lid is closed; deep sleep re-sleeps if the lid remains closed (06). Charging intentionally prevents deep sleep in shared code. - PMIC: AXP2202 —
/sys/class/power_supply/axp2202-battery/andaxp2202-usb/ - Battery:
capacity,status,voltage_now,temp,time_to_empty_now,time_to_full_now,charge_counter,health - Anbernic kernel extras under
axp2202-battery/:-
moto— rumble motor (write 1/0) — confirmed working -
work_led— small power-indicator LED, next to the charge LED. Present on every H700 model, unrelated to the RGB stick LEDs. Polarity is0=off, 1=on— an earlier note here had it backwards. Verified the same way on RG40XXV and RG28XX: the LED is lit through stock boot and goes out as soon as NextUI'slaunch.shwrites0. Plugging in USB lights it independently of any of this. The port writes0on wake and1on sleep (PLAT_enableBacklight), so in practice the LED marks sleep, not power. That is inherited from the old rg35xxplus port, is the same across models, and is deliberate — don't "correct" the polarity of those writes on the strength of the old comment. -
workled_sleep— LED behavior during sleep -
lowpwr_led,led_test -
mcu_pwr— power rail for the RGB LED MCU (write 1 to enable). See "RGB LEDs" below. -
hallkey— lid/hall sensor (RG34XXSP only; absent on RG40XXV) — polarity verified (1= open); lid close sleeps and lid open wakes screen-off. Deep suspend still requires power. POWER can wake light sleep while closed; deep sleep re-sleeps if the lid remains closed (06). -
brightness,display_id(panel variant id),spk_state,mcu_esckey,nds_esckey,boot_mode
-
-
/sys/class/pwm/pwmchip0exists (alternative rumble path;motois simpler)
Only three models have them: RG40XX H, RG40XX V, RG CubeXX (the same three muOS
flags with device/<dev>/config/led/rgb = 1; every other RG XX is 0).
An early probe concluded RG XX had no RGB LEDs. That was wrong. They are not exposed
as LED-class devices — on an RG40XXV /sys/class/leds is empty, there is no
led_anim driver (TrimUI only), and the device tree has no LED node. They hang off a
separate MCU reached over UART5:
-
/dev/ttyS5, 115200 8N1 raw (uart@05001400; char 248,5 — verified present) -
/sys/class/power_supply/axp2202-battery/mcu_pwrmust be1to power the MCU - Frame:
<mode> <brightness> <payload...> <checksum>, checksum =sum(preceding) & 0xFF, written as raw bytes. Brightness is one byte for the whole strip (0-255).- mode 1 solid — payload 8x(R,G,B) for one bank then 8x(R,G,B) for the other (16 positions in two banks of 8); the only mode with per-bank colour
- mode 2/3/4 breath fast/med/slow — payload 16x(R,G,B), one colour for all
- mode 5/6 rainbow mono/multi — payload
<1> <1> <speed 0-255>
- The MCU animates on its own, so there is no userspace animation in the port —
effect ids are translated onto these modes in
workspace/h700/platform/led.c. - Protocol source: muOS
MustardOS/internal,script/device/rgb.sh(SERIAL backend).
- WiFi: RTL8821CS (SDIO), module
8821cs; interfaceswlan0(+wlan1virtual);/sys/class/net/wlan0/operstatefor link state - Stock runs wpa_supplicant (
-u -sdbus mode) + NetworkManager + dnsmasq — the port stops NetworkManager and owns its own wpa_supplicant instance (07) -
WiFi does not recover on its own after
memsuspend — confirmed; the suspend script bounces it on resume (06/07) - Bluetooth:
rtl_btlpmmodule and stock BlueZ (5.66 on clean 2026 RG40XXV; 5.64 was observed on earlier firmware). The stock frontend normally runsrtk_hciattach -n -s 115200 ttyS1 rtk_h5, but NextUI replaces that frontend before it performs the attach, so the H700 init script must invoke the vendorsetBluetooth.shpath itself. - The clean 2026 RG40XXV image contains BlueALSA 4.2.0, its ALSA PCM/control
plugins, ALSA configuration, and D-Bus policy, contrary to the earlier probe
recorded here. Its
a2dp-sourceprofile successfully registers SBC media endpoints with stock BlueZ. NextUI uses these stock components directly and does not bundle or replace BlueALSA, its ALSA plugins, SBC, or BlueZ. Ubuntu has noudhcpc(DHCP =dhclient).
mmcblk0p1..4 special/boot-resource/env/boot (u-boot, kernel, DTB…)
mmcblk0p5 → / ext4 (Ubuntu rootfs)
mmcblk0p6 → /mnt/vendor ext4 (stock frontend, emulators, libs)
mmcblk0p7 → /mnt/data ext4 (also used as swap by loadapp.sh)
mmcblk0p8 → /mnt/mmc vfat (ROMs partition — user-visible FAT32; our dmenu.bin lives here)
- TF2 (second slot):
/dev/mmcblk1p1→ stock mountpoint/mnt/sdcard; the port mounts it itself when needed (vfat or exfat via helper, with fsck repair — see 02) - DTB is read raw from
/dev/mmcblk0by the old "Panel Fix" tool (offset 17954816, magicd00dfeed) - Kernel 4.9 has no native exfat; boot shim falls back through vfat → exfat → auto
systemd launcher.service → /etc/init.d/launcher.sh start → starts brightCtrl.bin +
cexpert + /mnt/vendor/ctrl/loadapp.sh → (swap, resize, retroarch cfg) →
/mnt/vendor/ctrl/dmenu_ln, which does:
CMD="/mnt/vendor/bin/dmenu.bin" # stock fallback
MISCBIN="/mnt/mmc/dmenu.bin" # ← OUR HIJACK POINT (FAT partition!)
if [ -f "/mnt/vendor/muos1.ini" ]; then MISCBIN="/mnt/vendor/bin/muos1.bin"; fi # stockmod!
if [ -f "/mnt/vendor/muos2.ini" ]; then MISCBIN="/mnt/vendor/bin/muos2.bin"; fi
[ -f $MISCBIN ] && CMD=$MISCBIN
...
if $CMD; then
[ -f /tmp/.next ] && sh /tmp/.next # chain-exec mechanism after CMD exits
fiConsequences:
-
Dropping an executable named
dmenu.binonto the FAT ROMs partition (/mnt/mmc) makes the stock OS run it instead of its own frontend. No reflashing. This is how the shipped port (and old MinUI, and muOS "in-place") installs. -
MU-style theme caveat: selecting stock/stockmod MU style 1/2 drops
muos1.ini/muos2.iniunder/mnt/vendor, which override the/mnt/mmc/dmenu.bincheck so the MU frontend runs instead. NextUI never starts and cannot show a warning from that path. Install requires stock old style theme (documented inskeleton/BASE/README.txt; see 02). -
/tmp/.nextchain-exec exists in the stock wrapper; NextUI runs its own launch loop. -
launcher.sh stopkills viaSIGUSR1 dmenu.bin— the shimtraps USR1. -
Model detection:
strings /mnt/vendor/bin/dmenu.bin | grep -m1 ^RG→RGXX_MODEL(stock display string).h700-device.shmaps that 1:1 to exactDEVICESKU tokens used for behaviour. Fallback detectors if the scrape ever breaks: fb0 mode480x640→ 28xx,xres/yresin /sys/class/disp,axp2202-battery/display_id, DTB lcd timings.Confirmed stock strings from vendor
dmenu.bin(p6 //mnt/vendor):RGSP,RG34xx,RG34xxSP,RG40xxH,RG40xxV,RG28xx,RGcubexx, and bareRG35xx(Plus and 2024 share that string →DEVICE=rg35xxplus). Unknown / empty scrapes fall back torg35xxplus(640×480, no sticks).
- Kernel
4.9.191 aarch64(TinaLinux/OpenWRT-flavored), glibc 2.33 -
/sys/power/state:freeze mem; same disp2 attrs incl.color_temperature; also no/sys/class/backlight - NextUI install:
/mnt/SDCARD/.system/tg5040/{bin,lib,cores,paks,shaders,etc}. SDL2 comes from the stock OS there — on H700 we bundle our own (04).
| kernel | arch | glibc | |
|---|---|---|---|
| TG5040 | 4.9.191 | aarch64 | 2.33 |
| H700 stock | 4.9.170 | aarch64 | 2.35 |
h700-toolchain-built binaries (GCC 8.3, glibc ≤ 2.33 from the TG5040 SDK sysroot,
aarch64, cortex-a53) load and run on the H700 stock OS unmodified — proven in
production by this port (first via the shared tg5040 image, now via dedicated
h700-toolchain). No ABI wall. (Caveat discovered the hard way: libc compatibility
is not the whole story — see the libasound symbol-versioning and libpng12 pitfalls in 01.)
- Last full commit at its canonical path:
8cd78866(git show 8cd78866:workspace/rg35xxplus/<path>). Renamed toworkspace/_unmaintained/infc9a5f3a, deleted in57e53bbe. - Was 32-bit (
arm-buildroot-linux-gnueabihf), toolchainLoveRetro/rg35xxplus-toolchain; custom SDL2 2.28.5 fromJohnnyonFlame/SDL-malifbdev-rot(the same repo the new port uses, rebuilt 64-bit) - Its sysfs inventory was the hardware-paths reference for this port; everything relevant
is re-verified and captured above. Remaining old-port material of interest:
- Panel geometry per model: default (RG35XX+/H/SP, RG40XX*) 640×480; RG34xx 720×480; RGcubexx 720×720 (only overscan-capable device); RG28XX physically 480×640 portrait
- Panel-fix DTB timing table (SKU fingerprints,
lcd_dclk_freq-lcd_ht-lcd_vt):24-770-526=35xx2024/Plus,24-770-528=35xxH,24-586-686=28xx,24-770-525=35xxSP,24-770-522=40xxH,36-812-756=CubeXX,26-820-536=34xx - HDMI machinery:
hdmimon.shvia/sys/kernel/debug/dispdbg+fbset(git show 8cd78866:skeleton/SYSTEM/rg35xxplus/bin/hdmimon.sh)
- Scope note: the old port is a hardware-paths reference only; its software architecture (SDL_Renderer compositing, 32-bit, pre-shader APIs) is obsolete. tg5040 was the code clone base.
- Real panel refresh rate —
SCREEN_FPS 60.0is assumed, never measured. - Exact stock
RGXX_MODELstrings for the RG35XX family. (RG40XXH is now confirmed asRG40xxH, read from its StockModdmenu.bin.) - RG SP support is derived entirely from firmware analysis — never run on the hardware. Panel geometry, stickless input, and the calibrated displaycal preset all need confirming on a real unit.