Watch
2
0
Fork
You've already forked ventura-scaler
0
Ventura TV scaler CLI and PRE_CTI writer guard Magisk module
  • Python 56.3%
  • Assembly 18.4%
  • C 14.9%
  • Shell 10.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-29 14:50:14 +03:00
inputs Track stock utpa2k binary as reproducible patch input 2026-10-29 14:50:14 +03:00
module Package persistent guard and verified scaler CLI as one Magisk module 2026-10-29 14:38:51 +03:00
src Package persistent guard and verified scaler CLI as one Magisk module 2026-10-29 14:38:51 +03:00
tests Package persistent guard and verified scaler CLI as one Magisk module 2026-10-29 14:38:51 +03:00
.gitignore Track stock utpa2k binary as reproducible patch input 2026-10-29 14:50:14 +03:00
build.sh Package persistent guard and verified scaler CLI as one Magisk module 2026-10-29 14:38:51 +03:00
README.md Track stock utpa2k binary as reproducible patch input 2026-10-29 14:50:14 +03:00

Ventura scaler + PRE_CTI guard

One Magisk module for CHiQ/DEXP Ventura Android 14:

  • Bind-mount a patched utpa2k.ko before init loads the TV driver.
  • Keep PRE_CTI off through the audited direct/PQ/MLoad/DS writer paths.
  • Expose scaler through Magisk's system/bin overlay.
  • Stay enabled across boots until disabled in Magisk.

No timer, polling process, auto-reapply service, firmware flash or driver reload. The boot script does not change scaler filter presets. CLI changes last until OEM picture/mode logic overwrites them; the driver guard persists separately.

Compatibility

Exact input driver SHA256: b50fc71ae0d147c081e09843764d8ca7818bd925399fcef8fee287292e0b8d0b

Kernel: 5.15.192++. Tested firmware family: CHiQ/G4FFDVB87/ventura:14/UKNV.260805.001/16021110:user/release-keys. The driver is ARM64; the CLI uses the ARM32 Utopia compat ABI, matching this TV's 32-bit Android userspace. Other firmware revisions need a separate analysis.

Install and use

Install the release ZIP in Magisk, then reboot. Module id stays ventura_pre_cti_guard, so it replaces the earlier guard module.

su -c 'scaler status'
su -c 'scaler nearest'
su -c 'scaler 4tap'

Presets:

  • nearest: bypass main and FO filter selectors. The name follows the observed integer-scale appearance; this code does not program a new coefficient table or mathematically guarantee nearest-neighbor output for every scaling ratio.
  • fo4: main bypass, FO Y/C filters enabled.
  • 4tap: main Y/C 4-tap selection, FO bypass.
  • 6tap, 8tap, 10tap: main Y tap selection, C 4-tap, FO bypass.
  • y4tap: main Y 4-tap, C bypass, FO bypass.
  • status: read filter registers and PRE_CTI bits, without picture writes.

The CLI checks ioctl results and readback. Failed changes attempt a masked rollback; rollback failure returns exit code 3 and reports uncertain state. Concurrent OEM mode switches can still race these operations. status showing OFF alone does not prove the guard is loaded. Read boot-check.log too.

The previous experimental /data/adb/scaler file is not needed. No replacement of the stock /product/bin/cli is installed. This package does not delete unrelated service.d scripts or files.

Code map

  • src/cli/scaler.c: register access, presets, verification and rollback.
  • src/driver/build-guard.py: exact-hash binary patcher and guard generator.
  • src/driver/guard-reference.S: original generated AArch64 stubs for review.
  • src/driver/verify-*.py: Unicorn tests of guards and driver instruction bodies.
  • module/post-fs-data.sh: checked early bind mount, no self-disable.
  • module/customize.sh: installer checks, permissions and old marker cleanup.
  • tests/: mock CLI and boot-script tests.
  • build.sh: full build, tests and release ZIP.

Git history retains the original CLI before error-handling fixes so the changes can be reviewed. All authored implementation code is here. OEM driver source was unavailable; the release includes a patched OEM binary, not a source-built replacement. The exact stock driver is tracked in inputs/utpa2k.ko as the patcher's input. Generated binaries and ZIPs stay in release assets.

Build

Linux x86_64, Android NDK r30 (30.0.14904198), Python 3 with pyelftools, capstone, unicorn, a host C compiler. Debian packages used for Python: python3-pyelftools python3-capstone python3-unicorn.

# The exact stock driver is included in inputs/utpa2k.ko.
export ANDROID_NDK_HOME=/path/to/android-ndk
PYTHON=/usr/bin/python3 ./build.sh

Output: dist/ventura-scaler-1.0.0.zip and dist/SHA256SUMS. The build uses the original enabled PQ row as a test fixture. The PQ database itself is not patched or bundled. Generated assembly, hook manifest and test reports are left under build/driver/ for inspection.

What the driver patch changes

PRE_CTI target: logical register 0x1323c2, bits 0x8004. Guards clear these value bits and expand a masked write to actively clear a previously enabled state. They preserve unrelated registers/bits and integer state outside the intentional argument changes.

14 relocation-free stubs are appended to .text. Hooks cover eight direct or MLoad entry points and six PQ decoding paths before queue construction. The fallback table's 12 enabled values are zeroed; the debug PRE_CTI=ON value becomes zero. Original symbol offsets, relocation bytes, module metadata and symbol versions are checked against the stock file.

This covers the audited paths in utpa2k; it is not a hardware MMIO access barrier. Unknown writers in other modules or root code can bypass it. Vertical, AI and POST CTI blocks are outside this patch's scope.

Validation includes 4704 differential stub cases, 45 patched profile/loader cases, 300 full direct-writer MMIO cases. The original guard was also loaded on the TV and a PRE_CTI=ON request read back zero. The combined package's next-boot installation is a separate check; building a ZIP is not a boot test.

Disable / rollback

Disable Ventura scaler + PRE_CTI guard in Magisk and reboot. This restores the stock file view and removes scaler from Magisk's overlay on the next boot. The running driver is never unloaded. No vendor partition bytes are modified. A broken boot may require Magisk module recovery; disabling a module does not replace the need for a working recovery path.