From 3c485ed311d2b7150c2e88081be3831b421d326c Mon Sep 17 00:00:00 2001 From: sssnake Date: Tue, 31 Mar 2026 07:28:08 -0700 Subject: [PATCH] Add rtl_tcp_andro as submodule for SDR driver app RTL-SDR + HackRF native Android driver (iqsrc:// protocol). Auto-installs APK during module flash if built. Build docs updated with instructions. --- .gitmodules | 3 +++ BUILDING_MODULES.md | 27 +++++++++++++++++++++++++++ build.sh | 33 +++++++++++++++++++++++++-------- customize.sh | 15 +++++++++++++++ driver-manager-v1.0.0.zip | Bin 11057 -> 15357 bytes tools/rtl_tcp_andro | 1 + 6 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 .gitmodules create mode 160000 tools/rtl_tcp_andro diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..344f3c4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tools/rtl_tcp_andro"] + path = tools/rtl_tcp_andro + url = https://github.com/signalwareltd/rtl_tcp_andro-.git diff --git a/BUILDING_MODULES.md b/BUILDING_MODULES.md index a288ffb..7ffe544 100644 --- a/BUILDING_MODULES.md +++ b/BUILDING_MODULES.md @@ -32,6 +32,33 @@ Some features need extra firmware or kernel modules you build yourself. **No kernel modules needed.** All SDR devices on Android use userspace USB libraries. The module handles USB permissions automatically. +**RTL-SDR + HackRF Driver App (rtl_tcp_andro):** + +This module includes the source for the Android RTL-SDR/HackRF driver app +([rtl_tcp_andro](https://github.com/signalwareltd/rtl_tcp_andro-.git)) as a +submodule in `tools/rtl_tcp_andro/`. It implements the rtl_tcp protocol natively +on Android via USB OTG — no root needed for the app itself. + +To build the APK: +```bash +cd tools/rtl_tcp_andro +./gradlew assembleRelease +``` + +The APK will be at `app/build/outputs/apk/release/app-release-unsigned.apk`. +Copy it to `apk/rtl_tcp_andro.apk` and rebuild the module zip — the installer +will auto-install it on the device. + +Or install directly: +```bash +adb install app/build/outputs/apk/release/app-release-unsigned.apk +``` + +The app provides an `iqsrc://` intent that any SDR client app can use to +receive I/Q samples from RTL-SDR, HackRF, or SDRplay hardware. + +Supported hardware: RTL-SDR (all versions), HackRF One, SDRplay RSP + **Setup in Termux:** ```bash diff --git a/build.sh b/build.sh index 6fdbea4..8fa9908 100755 --- a/build.sh +++ b/build.sh @@ -5,14 +5,31 @@ cd "$(dirname "$0")" ZIP="driver-manager-v1.0.0.zip" rm -f "$ZIP" -zip -r9 "$ZIP" \ - module.prop \ - customize.sh \ - post-fs-data.sh \ - service.sh \ - system.prop \ - system/ \ - webroot/ \ +# Include built APK if available +mkdir -p apk +RTL_APK="tools/rtl_tcp_andro/app/build/outputs/apk/release/app-release-unsigned.apk" +if [ -f "$RTL_APK" ]; then + cp "$RTL_APK" apk/rtl_tcp_andro.apk + echo "Including rtl_tcp_andro APK" +fi + +FILES=( + module.prop + customize.sh + post-fs-data.sh + service.sh + system.prop + system/ + webroot/ + BUILDING_MODULES.md +) + +# Include APK dir if it has files +if [ -f "apk/rtl_tcp_andro.apk" ]; then + FILES+=(apk/) +fi + +zip -r9 "$ZIP" "${FILES[@]}" \ -x "*.git*" "build.sh" "tools/*" "README*" echo "Built: $ZIP ($(du -h "$ZIP" | cut -f1))" diff --git a/customize.sh b/customize.sh index 5d7b74b..00792e1 100644 --- a/customize.sh +++ b/customize.sh @@ -46,6 +46,21 @@ echo "24M:1800M" > "$MODPATH/config/spectrum_range" mkdir -p "$MODPATH/modules" mkdir -p "$MODPATH/firmware" +# Install rtl_tcp_andro APK if built +RTL_APK="$MODPATH/apk/rtl_tcp_andro.apk" +if [ -f "$RTL_APK" ]; then + pm install -r "$RTL_APK" 2>/dev/null + if [ $? -eq 0 ]; then + ui_print "- RTL-SDR + HackRF driver app installed" + else + ui_print "! Failed to install RTL-SDR driver app" + ui_print "! Install manually from apk/ directory" + fi +else + ui_print "- RTL-SDR driver app not built yet" + ui_print " Build with: cd tools/rtl_tcp_andro && ./gradlew assembleRelease" +fi + ui_print "- Default config written" ui_print "- Kernel module dir: modules/" ui_print "- Firmware dir: firmware/" diff --git a/driver-manager-v1.0.0.zip b/driver-manager-v1.0.0.zip index c40ece5dbc5d6e3e8a5eca5cfee7321000cf97dc..719dd1dba1006edb4758991d767fd87f20518ac2 100644 GIT binary patch delta 12633 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