#!/usr/bin/env python3 """Fix: a stale "this frame is packet data" marker could suppress the Voice LC Header of an ordinary voice transmission. hrc.txDataType is only ever set on the hotspot path, and was only cleared after a data burst was actually sent. If a data transmission was cut short before that, the marker stayed set - and the next PTT from the radio itself started without a Voice LC Header, so receivers never recognised the call. Two guards: - the start-of-transmission checks now only apply while acting as a hotspot modem; - the marker is cleared whenever a normal (non-hotspot) transmission begins. """ W = "/home/viktor/ogd77rel/uv_src/OpenGD77_MDUV380_DM1701_20260130/MDUV380_firmware/application" p = W + "/source/hardware/HR-C6000.c" s = open(p).read() if "isHotspotDataTx" in s: print("already patched") raise SystemExit(0) # 1. helper right after the struct instance, so all three call sites can use it anchor = "\t\t.txDataType = HOTSPOT_TX_TYPE_VOICE,\n" assert anchor in s, "hrc initialiser not found" # find the end of the initialiser block to place the helper after it marker = "static void hrc6000SendPcOrTgLCHeader(void);" assert marker in s, "forward declaration anchor not found" helper = """// True only when the frame about to be sent is a packet data burst queued by the host. // Outside hotspot mode there is no such thing, so ordinary voice transmissions are never // affected by a leftover marker. static inline bool isHotspotDataTx(void) { return ((settingsUsbMode == USB_MODE_HOTSPOT) && (hrc.txDataType != HOTSPOT_TX_TYPE_VOICE)); } """ s = s.replace(marker, marker + "\n" + helper, 1) # 2. use it in the three start-of-transmission checks a1 = "\t\t\tif (hrc.txDataType != HOTSPOT_TX_TYPE_VOICE)\n\t\t\t{\n\t\t\t\t// A data burst is queued: don't announce a voice call in front of it." assert a1 in s, "TX_START_1 check not found" s = s.replace(a1, "\t\t\tif (isHotspotDataTx())\n\t\t\t{\n\t\t\t\t// A data burst is queued: don't announce a voice call in front of it.", 1) a2 = "((hrc.txDataType != HOTSPOT_TX_TYPE_VOICE) ? (DT_IDLE << 4) : 0x10)" n2 = s.count(a2) assert n2 == 2, "expected 2 shared checks, found %d" % n2 s = s.replace(a2, "(isHotspotDataTx() ? (DT_IDLE << 4) : 0x10)") # 3. and in the ongoing-TX branch, so a stale marker cannot divert voice frames either a3 = "\t\t\t\t\tif (hrc.txDataType != HOTSPOT_TX_TYPE_VOICE)\n" assert a3 in s, "TX_2 data branch not found" s = s.replace(a3, "\t\t\t\t\tif (isHotspotDataTx())\n", 1) # 4. belt and braces: clear the marker when a non-hotspot transmission starts a4 = """ if (settingsUsbMode != USB_MODE_HOTSPOT) { codecInit(false); } else { hrc.hotspotPostponedFrameHandling = (HS_NUM_OF_SILENCE_SEQ_ON_STARTUP * 6);""" assert a4 in s, "TX start branch not found" s = s.replace(a4, """ if (settingsUsbMode != USB_MODE_HOTSPOT) { hrc.txDataType = HOTSPOT_TX_TYPE_VOICE;// plain voice call: never a data burst codecInit(false); } else { hrc.hotspotPostponedFrameHandling = (HS_NUM_OF_SILENCE_SEQ_ON_STARTUP * 6);""", 1) open(p, "w").write(s) print("HR-C6000.c: voice transmissions can no longer be suppressed by a stale data marker")