Repository navigation
Add QRP Labs QMX via the hamlib backend - #925
laniol8926 wants to merge 1 commit into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #925 +/- ##
=========================================
Coverage 41.51% 41.51%
Complexity 252 252
=========================================
Files 280 280
Lines 33993 33993
Branches 4034 4034
=========================================
Hits 14112 14112
Misses 19592 19592
Partials 289 289
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
@patrickrb — flagging this directly in case it gets buried under the Codecov bot comment. This change is small (one line in Would you be able to either:
No rush — happy to wait on whichever's easier on your end. |
The rig catalog (rigaddress.txt) had no entry for the QMX at all, so it never showed up as a selectable rig. Its sibling QDX is listed using the generic Kenwood TS-590/480 command set, but that path sets MD2 (SSB-USB voice mode) rather than the DATA mode + TX-rise-threshold tuning the QMX specifically needs to transmit -- same bug danleetw/FT8TW's native app had to hand-patch around. FT8AF already vendors and statically compiles hamlib 4.7.2, which has a dedicated QRP Labs QMX backend (qrplabs_qmx_caps / RIG_MODEL_QRPLABS_QMX), exposed through the existing HamlibRig bridge -- the same mechanism already used for "Yaesu FT-891 (Hamlib)". This adds the matching catalog line: 0x809 = RIG_MAKE_MODEL(RIG_KENWOOD, 57), hamlib's real QMX model ID, at its minimum supported baud rate (9600). Per QRP Labs' own current QMX firmware guidance, the native hamlib definition is the recommended path over Kenwood emulation, which matches this change. Appended at the end of rigaddress.txt (after ICOM IC-7300MK2), per RigAddressAssetTest's documented append-only invariant -- the selected rig is persisted as a raw list index, so inserting anywhere else would silently reassign every existing user's selected rig on upgrade. Added a matching GOLDEN_ORDER entry, moved the "last entry" pin from the MK2 test to this one, and added a dedicated test (qmxHamlib_isListedWith HamlibModelId) mirroring the existing ic7300mk2_isListedWithIcomDefaults pattern. Verified: builds cleanly through resource merge, manifest processing, and Java/Kotlin compilation on this checkout; the new/changed test assertions were traced by hand against RigNameList's parser (confirmed "809" parses as hex -> 2057 = 0x809) since this environment can't execute them. Could not produce a final APK or run the JVM unit tests locally -- the AGP-bundled aapt2 for Linux is x86_64-only and this build machine is aarch64 (processDebugResources, a dependency of both assembleDebug and testDebugUnitTest, needs it to compile AAR resources). qemu-user-static emulation was attempted but blocked by an unrelated, unsafe apt dependency conflict in this machine's repo configuration (would have required upgrading libc6 system-wide, so it was not forced through). No QMX hardware was available to test TX/RX against either. All three are red flags a reviewer with access to any of them should check before merge -- CI (real x86_64 runners) is this PR's actual first verification. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SaooA8HLsiETQ12Tbwwyzf
9e6a274 to
1d138cd
Compare
|
Tested this on real QMX hardware (arm64 debug build from this branch, sideloaded). CAT control works — confirms the fix itself: But TX audio write fails — separate, pre-existing bug, not introduced by this PR's diff: Also saw the whole USB connection to the QMX fully detach and reattach twice during the session, independent of the TX attempt: I initially suspected old-phone/cable flakiness (this is a 2015 Moto G 3rd Gen), but ruling that out: both the cable and this exact phone have already done reliable, sustained live QMX work — same cable is the one in daily use with a different always-on QMX setup, and this same phone has already done live FT8 decoding over USB with a different native Android FT8 app with no equivalent dropouts. So this looks like something specific to FT8AF's direct-libusb audio path or its interaction with the CAT connection on this device, not the hardware. Given CAT itself works end to end, I think this PR's change is sound — the TX-audio-write and USB-detach issues look like a separate, pre-existing bug surfaced by QMX now being reachable at all. Happy to pull more of |
|
One more real-hardware finding: changing bands in the app did not actually retune the radio. Confirmed by direct observation (watching the QMX itself), not just the log — the first band change (to 7074000/40m) did take effect, but a later change to 14074000/20m did not; the radio stayed on 40m. I can't fully root-cause this from `debug.log` alone, and want to flag why precisely: `HamlibRig.setFreqToRig()` submits `HamlibNative.nativeSetFreq()` to an async worker and only logs a failure via `Log.w` (logcat) if `rc != 0` — that line never reaches `fileLog()`/`debug.log`. I don't have `adb`/logcat access in this environment, so I can't see whether the native call actually returned a nonzero `rc` for that second band change or silently no-op'd for some other reason. The `debug.log` lines around it: |
|
Found the precise mechanism behind "transmitting but no audio reaches the radio" (and probably the earlier "good audio level but no waterfall/decodes" too): after a USB detach/reattach, the serial/CAT side reconnects correctly, but the USB audio side silently falls back to the phone's own mic/speaker and never reacquires the QMX. Sequence from `debug.log`: So the earlier "libusb native write FAILED (rc=-1 IO)" report and this one may be two different faces of the same underlying USB-audio-device-tracking issue (one still attempting and failing the libusb write, this one having given up on USB audio entirely and not noticing) — or two separate bugs. Either way, the common thread across all three things reported on this PR is: the USB audio side of the connection is noticeably less resilient to reattach/reconnect events than the CAT/serial side, and it fails silently rather than surfacing to the user or retrying. |
|
Follow-up on the band-retune issue above, with a harder confirmation: watching the QMX's own display directly (not just the app or the log), the radio's actual frequency stayed at 7074 (40m) when the app was commanded to switch to the 20m FT8 frequency (14074). This matches the `debug.log` sequence from that attempt: |
|
Ruling out the hardware definitively: the same QMX and same USB cable work completely normally under WSJT-X (running directly on the machine that was hosting the phone's MTP connection during this testing) — CAT, frequency control, and audio all fine there. So the three issues reported above (TX audio silently falling back to the phone's own speaker after a USB reattach, the radio not always retuning on a band change, and the earlier intermittent full USB detaches) are software-side in FT8AF, not the radio or cable. |
|
One more hardware variable ruled out: all of the phone-side testing above was repeated across two different USB-OTG cables/adapters between the phone and the QMX, with the same symptoms both times. Combined with the WSJT-X result above, that's the radio, the Quadra-side cable, and now both OTG cables all cleared — this is squarely software in FT8AF. |
|
Last piece of hardware-elimination: installed a different native Android FT8 app (danleetw/FT8TW) on a different, older Samsung Galaxy phone against the same QMX, and it's getting real decodes with no issues. So this isn't specific to the Moto G 3rd Gen used in the testing above either — two different phones, two different apps, same radio: only FT8AF shows the symptoms reported in this thread. That's about as clean a "software, not hardware" signal as this setup can produce. |
|
Correction/update to everything above — new evidence changes the picture significantly, and I want to flag that clearly rather than let the "it's FT8AF software, not hardware" framing in my earlier comments stand as the final word. Summary of a cleaner round of testing:
Two independently-written apps, same split, same phones, same radio. That's a strong signal this is an Android 15 platform-level change, not a bug in either app's code. The specific clue: on Android 15, plugging in the QMX only shows the standard "which app do you want to open this with" chooser — no separate USB-device-access permission dialog appears, for either app. On Android 13, the explicit permission prompt does show. CAT/serial still works on Android 15 (likely covered by whatever implicit grant comes from the app-chooser/intent-filter match), but USB Audio Class access needs its own explicit I don't have logcat access in my environment to confirm the exact permission-API-level mechanism, but given it reproduces identically in two unrelated codebases, I'd treat this as an Android-version compatibility issue to track (and maybe worth a GitHub issue of its own, separate from this PR) rather than something to chase inside FT8AF's own USB-audio code. Apologies for the earlier, more confident "it's definitely FT8AF" framing — should have held that more loosely given how early those comments were in the testing. |
|
One more refinement, and this is good news: tried a third app on the same Android 15 Moto G — QFT8, which was written specifically for the QMX — and it gets real decodes, no issue. So this isn't an unconditional Android 15 platform block after all. It's narrower than that: whatever FT8AF and danleetw/FT8TW are both doing (or not doing) to request/claim the USB Audio Class interface doesn't work on Android 15, but QFT8's approach does. That means there's a working reference implementation to compare against — this is a fixable Android-15 compatibility bug in the USB-audio permission/claim flow, not something to just wait out. I don't have QFT8's source to compare against, but if anyone has access to it (or wants to sniff what permission calls it makes vs. what |
|
Closing summary of the real-hardware testing on this PR, pulling the thread above together:
Conclusion: this isn't something to wait out — it's a known-fixable gap. FT8AF (and FT8TW, separately) would benefit from updating USB-audio permission/claim handling to work on current Android versions, ideally informed by comparing against how QFT8 does it. Worth its own tracking issue separate from this PR, since it's pre-existing and affects every USB-audio rig, not just the QMX. Happy to help narrow it down further if useful — thanks for bearing with the long comment thread while this got untangled. |
|
I love this, thank you! |
Summary
rigaddress.txt) had no entry for the QMX at all, so it never showed up as a selectable rig in Settings.MD2(SSB-USB voice mode) rather than DATA mode + the TX-rise-threshold tuning the QMX specifically needs to transmit — the same bugdanleetw/FT8TW's native app had to hand-patch around (MD6;Q41;).qrplabs_qmx_caps/RIG_MODEL_QRPLABS_QMX), exposed through the existingHamlibRigbridge — the same mechanism already used for "Yaesu FT-891 (Hamlib)". This adds the matching catalog line:0x809=RIG_MAKE_MODEL(RIG_KENWOOD, 57), hamlib's real QMX model ID, at its minimum supported baud rate (9600).ICOM IC-7300MK2), perRigAddressAssetTest's documented append-only invariant — the selected rig is persisted as a raw list index, so inserting it mid-file (my first push here, now fixed) would have silently reassigned every existing user's selected rig on upgrade. UpdatedGOLDEN_ORDER, moved the "last entry" pin test off the MK2 entry onto this one, and addedqmxHamlib_isListedWithHamlibModelIdmirroring the existingic7300mk2_isListedWithIcomDefaultspattern.Known gaps — please check before merging
aapt2for Linux is x86_64-only, andprocessDebugResources(a dependency of bothassembleDebugandtestDebugUnitTest) needs it to compile AAR resources. qemu-user-static emulation was attempted but blocked by an unrelated, unsafe apt dependency conflict in that machine's repo config (would have required upgradinglibc6system-wide, so it was not forced through). The new/changed test assertions were traced by hand againstRigNameList's parser instead (confirmed"809"parses as hex →2057=0x809) — CI on a real x86_64 runner is this PR's actual first execution.HamlibRigwiring) but not verified against a real radio.Test plan
testDebugUnitTestshould now pass with the golden-order fix)./gradlew assembleDebug) on a supported dev machine (Windows/macOS perAGENTS.md)🤖 Generated with Claude Code
https://claude.ai/code/session_01SaooA8HLsiETQ12Tbwwyzf