- flash_system.sh: rename ota_tar -> system_tar (path is staged
release-artifacts/<sku>/system.tar, not output/image/update_ota.tar)
and only re-check device reachability after a --build, not on every
invocation.
- common.sh: add require_arg and prompt for SKU via normalize_system_sku
so aliases live in one place; align FLASH_SKU/SYSTEM_SKU precedence
between build_system.sh and flash_system.sh.
- check_device.sh (new): one wrapper around check_ping/check_ssh used
by both make check_device and direct CLI, removing the Makefile's
hardcoded ping -c 1 / root@ duplication.
- release_r2.sh, release_github.sh, run_e2e_tests.sh, build_system.sh,
flash_system.sh: route all value-taking options through require_arg
for consistent missing-arg errors.
- flash_system.sh: rename ota_tar -> system_tar (path is staged
release-artifacts/<sku>/system.tar, not output/image/update_ota.tar)
and only re-check device reachability after a --build, not on every
invocation.
- common.sh: add require_arg and prompt for SKU via normalize_system_sku
so aliases live in one place; align FLASH_SKU/SYSTEM_SKU precedence
between build_system.sh and flash_system.sh.
- check_device.sh (new): one wrapper around check_ping/check_ssh used
by both make check_device and direct CLI, removing the Makefile's
hardcoded ping -c 1 / root@ duplication.
- release_r2.sh, release_github.sh, run_e2e_tests.sh, build_system.sh,
flash_system.sh: route all value-taking options through require_arg
for consistent missing-arg errors.
* feat(release): ship update_sd.img.zip as SDMMC recovery artifact
The SDMMC update.img is a packed Rockchip update image, not a raw disk
image, so it can't be written to a microSD card. Publishing it next to
the real recovery zip just confuses users. Move SDMMC over to
update_sd.img.zip everywhere it's staged, uploaded, or attached:
- common.sh: add recovery_artifact_for_sku() and recovery_source_for_sku()
so all release scripts agree on which file is the per-SKU recovery
image and where it lives in the build output. Mirrors the
RECOVERY_ARTIFACT_BY_SKU map in cloud-api. Unknown SKUs fail loudly.
- build_system.sh: stage only the SKU's recovery artifact -- eMMC keeps
update.img, SDMMC ships update_sd.img.zip. update.img is still built
for SDMMC as a side effect; we just stop copying it into staging.
- release_r2.sh: validate/print/upload the SKU's recovery artifact, so
R2 receives system.tar + update_sd.img.zip (+ .sha256s) for SDMMC and
system.tar + update.img for eMMC.
- release_github.sh: drop update-sdmmc.img from the GitHub release
asset list (update_ota-sdmmc.tar and update_sd.img.zip stay).
Pairs with a cloud-api change that points
/releases/system_recovery/latest?sku=jetkvm-v2-sdmmc at the new zip.
* fix(release): propagate unknown-SKU failure from recovery_source_for_sku
recovery_source_for_sku embedded recovery_artifact_for_sku inside echo's
argument via $(...). On an unknown SKU the inner exit 1 only killed the
command-substitution subshell; echo still ran with a partial path and
returned 0, swallowing the intended hard failure and producing a bogus
path. Capture the artifact separately and propagate the non-zero status
so callers actually abort with the original error message.
update_app.sh now requires a SKU and downloads from
api.jetkvm.com/releases/app/latest?sku=<sku>, so SDMMC and EMMC builds
get the matching app binary instead of sharing one.
Build script downloads the binary inside each variant build, and CI
passes the SKU from the matrix.
* feat(release): add SKU system release flow
Build and stage both storage variants so releases can publish SKU-specific system OTA and recovery artifacts without changing existing EMMC asset names.
* fix(release): clean root-owned output between SKU builds
Mirror the top-level clean path before switching from SDMMC to EMMC so root-owned SDK output does not break the intermediate cleanup.
* fix(release): quiet noisy build steps
Move build cleanup into the build wrapper and capture verbose SDK output in release-artifacts logs while keeping wrapper progress and failure diagnostics visible.
* fix(release): address release script review findings
Preserve quiet build command failures and stage uniquely named GitHub assets before creating releases.
* feat(release): sign production OTA uploads
Require an approved signing key for production releases and publish a detached OTA signature to R2 while keeping dev uploads unsigned.
* ci: use ubuntu-latest runner
Switch the build workflow off the custom runner label so GitHub Actions uses the default hosted Ubuntu image.
* fix(release): check signing key before running release
Make the signing key verification a release prerequisite so production builds fail early and the release target stays consistent with its declared dependencies.
* fix(release): make OTA signing explicit
Keep production releases failing fast on missing GPG keys while making R2 upload signing an explicit script option.
* feat: support dual storage variants (eMMC + SDMMC/TF card) and upgrade jetkvm_app to 0.5.6
Introduce two separate build configurations for JetKVM V2 hardware
variants that differ only in storage medium:
BoardConfig-EMMC-NONE-RV1106_JETKVM_V2.mk → boots from eMMC (mmcblk0, 13640M userdata)
BoardConfig-SDMMC-NONE-RV1106_JETKVM_V2.mk → boots from TF card (mmcblk1, dynamic userdata)
DTS refactor:
- Extract all shared board peripherals (backlight, gmac, i2c1/AT24C02,
i2c3/FT5x06, spi0/ST7789V, uart3, rtc, wdt, pwm5, sfc=disabled) into
rv1106-jetkvm-v2.dtsi as a common base
- rv1106g-jetkvm-v2.dts becomes a thin file with only the eMMC node
- New rv1106g-jetkvm-v2-sdmmc.dts thin file with only the sdmmc node
- Verified: both DTBs compile correctly; eMMC DTB is binary-identical
to upstream
Build system:
- Add sdmmc as a new RK_BOOT_MEDIUM type throughout project/build.sh:
sd_parts device, parse_partition_file, rootfs bootarg, build_recovery,
build_factory, build_uboot INI selection, and mount_part script
- sysdrv/Makefile: add sdmmc block for KERNEL_CMDLINE_FRAGMENT and env
target using mmcblk1; restore emmc back to mmcblk0
- project/scripts/mk-tftp_sd_update.sh: recognize sdmmc alongside emmc
- tools/linux/Linux_Pack_Firmware/mk-update_pack.sh: add mmcblk0 to the
boot medium list so eMMC update packages are correctly generated
U-Boot:
- android_ab.c: replace hardcoded mmcblk1 with dev_desc->devnum so the
A/B root device path is correct for both eMMC (devnum=0) and SDMMC
(devnum=1), matching the DTS alias assignments
jetkvm_app:
- Upgrade from 0.4.8 to 0.5.6 (SHA256 verified)
- Note: 0.5.6 switches from static to dynamic linking (ld-uClibc.so.0)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: switch to ubuntu-22.04 runner and build both EMMC and SDMMC variants
- Replace buildjet-16vcpu-ubuntu-2204 with standard ubuntu-22.04 runner
- Use matrix strategy (fail-fast: false) to build EMMC and SDMMC in parallel
- Artifact names include board variant: OTA-Image-EMMC, Full-Image-EMMC, etc.
- buildkit upload remains EMMC-only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: bake SKU identifier into system image for OTA targeting
Each build variant writes /etc/jetkvm-sku to the system partition so
the jetkvm_app can report the correct SKU when querying the OTA service:
BoardConfig-EMMC → RK_SKU=jetkvm-emmc
BoardConfig-SDMMC → RK_SKU=jetkvm-sdmmc
Matches the SKU routing introduced in jetkvm/cloud-api#49, where the
OTA API serves variant-specific binaries under
{prefix}/{version}/skus/{sku}/ and defaults to legacy path for
unrecognised SKUs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: align OTA SKU names with cloud-api DEFAULT_SKU convention
jetkvm-emmc → jetkvm-v2 (matches cloud-api DEFAULT_SKU)
jetkvm-sdmmc → jetkvm-v2-sdmmc
Ref: jetkvm/cloud-api@1958830
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(dts): remove contradictory cap-mmc-highspeed from sdmmc node
no-mmc prevents MMC protocol probing entirely, making cap-mmc-highspeed
dead and misleading. Only cap-sd-highspeed is relevant for TF card use.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: handle IGNORE mountpoint for sdmmc in mount_part script
Line 1601's guard only matched emmc, so SDMMC partitions with
IGNORE mountpoint (e.g. inactive A/B slot) would fall through to
return 1 instead of return 0, causing boot-time mount errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add sdmmc to block-device filesystem tool checks in build_mkimg
erofs and squashfs paths were missing sdmmc, causing them to fall
through to ubifs (NAND-only tool). Latent with current ext4-only
config but would silently produce a corrupt image if fs type changed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(sdmmc): build dd-able SD card image for direct flashing
Adds build_sd_dd_image() that assembles a flat raw image from the
fixed-size partitions (env, idblock, uboot_a/b, boot_a/b, system_a/b)
plus a 256 MiB seed userdata.img containing install_to_userdata
content (jetkvm_app etc.). Layout follows the cmdline blkdevparts —
no MBR/GPT, since the kernel reads partitioning from u-boot env.
Why a seed userdata: the SDMMC partition spec terminates with
'-(userdata)' which build_mkimg skips, so jetkvm_app never landed in
update.img on SDMMC. The mount_part init script (project/build.sh
mount_part) calls resize2fs on first boot, which grows the 256 MiB
ext4 to the end of the SD card automatically.
Workflow: SDMMC artifact is now update_sd.img.zip (zip -9 of a sparse
~1.4 GiB image, ~45 MiB compressed). update.img remains the EMMC
artifact since RKDevTool still uses it for production flashing.
* fix(sdmmc): chown userdata seed root:root before mkfs.ext4
build_mkimg userdata is a no-op on SDMMC (partition size '-' → 0), so the
__RELEASE_FILESYSTEM_FILES chown that build_mkimg normally runs never fires.
Without it, mkfs.ext4 -d preserves the builder's uid/gid into the image, so
/userdata/jetkvm on the SD card depended on whoever ran the build.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(sdmmc): tune userdata mkfs.ext4 so first-boot resize2fs scales to 1 TiB
The previous flags (mkfs default 1K block size, -O ^64bit,^huge_file) made
the first-boot resize hang on large cards:
- 1K blocks × 8K-blocks-per-group → 128K block groups for 1 TiB. resize2fs
has to write GD/bitmap entries for every new group; on slow SD random
writes this stretches to many minutes.
- Default inode_ratio at 1K = 2048 inodes/group → ~256M inodes after
resize. ext4lazyinit kthread then zeroes ~32 GiB of inode tables in
the background, saturating SD I/O long after mount returns.
- resize_inode reserve = 256 GDT blocks × 32 entries = 8192 group
descriptors, capping resize_inode-style growth at 64 GiB. Beyond that,
resize2fs falls back to meta_bg, but ^64bit blocks the cleaner path.
Switch to: 4K blocks, -T largefile (1 inode/MiB), -O 64bit, and an explicit
-E resize= reservation covering 2 TiB. Measured on a 1 TiB sparse loop
(host mkfs.ext4 1.47.2): online resize drops from 40 s to 0.4 s, and the
post-mount lazy-itable workload drops from ~32 GiB to ~256 MiB of writes.
32 GiB minimum supported card capacity.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(sdmmc): include sdmmc in sysdrv build-medium switches
Three places in sysdrv/ branched on the boot medium but left sdmmc out:
- Makefile.tools.board.mk: e2fsprogs was gated on BOOT_MEDIUM=emmc, so
the SDMMC rootfs shipped without resize2fs/e2fsck/mke2fs. mount_part's
first-boot resize2fs call then silently failed and userdata stayed
locked at the 256 MiB seed size, never growing to fill the card.
- Makefile.param: the RK_BOOT_MEDIUM whitelist that propagates BOOT_MEDIUM
omitted sdmmc, so any sub-tool Makefile included Makefile.param
standalone (dropbear, eudev, etc.) saw BOOT_MEDIUM unset for sdmmc.
Currently benign because no sub-tool branches on BOOT_MEDIUM, but a
latent footgun.
- tools/pc/toolkits/get_part_info.sh: PARTITION_FIRST_NO=0 was applied
only for emmc. mmcblk1pN is also 1-indexed, so sdmmc would produce
off-by-one root=/dev/mmcblk1pN values via `make env -C sysdrv`. The
project's build.sh path computes part_num itself and isn't affected,
but the sysdrv path was wrong.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The edt-ft5406 touchscreen node had no threshold property, leaving the
chip at its hardware default of 0 (zero noise rejection). This makes
the controller susceptible to phantom touch events from EMI or power
supply ripple, which users report as the device randomly opening the
Settings screen without physical interaction.
Set threshold to 40 to provide reasonable noise rejection while
maintaining touch responsiveness.
* usb: gadget: f_hid: add wakeup_on_write support
Add an opt-in wakeup_on_write configfs attribute to the HID function
driver. When enabled, each write to /dev/hidgN calls
usb_gadget_wakeup() before queuing the USB request, allowing HID input
to wake a suspended host.
The configuration descriptor must also advertise remote wakeup capability
(bmAttributes bit 5) for the host to arm the feature during enumeration.
This is useful for KVM-over-IP devices that need to wake a sleeping host
machine by sending keyboard or mouse input.
Tested on JetKVM v2 (RV1106 SoC, DWC3 v3.30a) waking a Windows 11 host
from S3 sleep via Intel xHCI USB 3.1 controller. Host wakes in ~4
seconds from HID keystroke.
Closes: https://github.com/jetkvm/kvm/issues/120
Closes: https://github.com/jetkvm/kvm/issues/674
* fix: guard func.config dereference in f_hidg_write
Move the hidg->func.config->cdev dereference inside the
wakeup_on_write guard block and add a NULL check on func.config
before accessing cdev. This prevents a potential NULL pointer
dereference if f_hidg_write races with unbind, where func.config
can be NULL before the spinlock is acquired.
The cdev variable was only used for the wakeup call, so scoping
it to the guard block is safe.
The tun_get() function has a race condition where tun->dev can become
NULL between checking tun and calling dev_hold(tun->dev).
This occurs when tun_detach_all() runs concurrently:
1. tun_get() calls rcu_dereference(tfile->tun), gets valid tun
2. Another thread calls tun_detach_all() which sets tun->dev to NULL
3. dev_hold(tun->dev) dereferences NULL pointer -> kernel crash
Fix by reading tun->dev into a local variable with READ_ONCE() and
verifying both the pointer and device registration state before
taking the reference.
Crash signature:
Unable to handle kernel NULL pointer dereference at virtual address 00000004
PC is at tun_get+0x16/0x22 [tun]
Require JETKVM_REMOTE_HOST for E2E tests and pass it through to the kvm
repo's make test_e2e. Add check_device/check_remote Makefile targets that
verify ping+SSH before starting the build. Remove redundant `make frontend`
call (already done inside test_e2e). Show target device IP in flash output.
* build: bump version to 0.2.8
* Remove non-used script
* Add tests, dev and prod release scripts
* Refactor release process and update Makefile
- Updated Makefile to ensure `dev_release` and `release` targets check for existing GitHub releases and tags with the new naming convention `release/v<version>`.
- Modified `dev_release` to depend on `git_check_dev` and `test` targets.
- Removed obsolete `release_github.sh` and `release.sh` scripts, consolidating functionality into `release_r2.sh`.
- Adjusted build scripts to improve error handling and output consistency.
- Updated GitHub Actions workflow to trigger on pull requests instead of specific branches and tags.
* Release to r2 before making GH release
* Set BUILD_VERSION for the update and system images
* Better log msg
* Refactor build scripts to use variables for args
Optimize TC358743 audio capture to eliminate artifacts and improve
audio fidelity:
- Disable automatic audio muting (AUTO_CMD0/AUTO_CMD1) to prevent
ACR PLL instability during silence periods
- Reduce audio initialization delay from 500ms to 200ms for faster
startup after HDMI format changes
- Disable sample rate-based muting (FS_MUTE) to prevent false muting
- Tighten ACR clock tolerance from 976/1976/3906 PPM to 122/122/244 PPM
for 8-32x better audio clock tracking precision
- Increase divider settling time from 100ms to 600ms to eliminate
artifacts during video resolution changes
- Explicitly configure 24-bit I2S sample depth
- Add V4L2_CTRL_FLAG_VOLATILE to audio_sampling_rate control to enable
dynamic sample rate detection from userspace
These changes eliminate crackling and clipping artifacts during silence
transitions and format changes, while providing significantly tighter
audio clock synchronization with the HDMI source. The 122/244 PPM
tolerance provides excellent audio quality while maintaining wide
compatibility with consumer HDMI devices (typically 20-50 PPM crystal
accuracy).