DMR-данные (SMS) на TYT MD-UV380 под OpenGD77
Восстановлено из транскрипта сессии после потери рабочего дерева на сервере сборки. Что внутри: - четыре новых модуля прошивки (приём, сборка исходящего, меню Messages); - правки существующих файлов в виде скриптов, с порядком применения; - инструменты стенда: снятие экрана рации по USB, дамп кадров, эталонная сборка пакета; - NOTES.md: что проверено в эфире, что не доделано, где грабли. Работало в эфире в августе 2026: данные ходят в обе стороны в режиме хотспота, рация принимает SMS и показывает на экране. Отправка собрана и сверена с эталоном сервера побайтово, но в эфире не проверялась. Claude-Session: https://claude.ai/code/session_01GJtvG5WwqYNe1b7s9LLtgy
Этот коммит содержится в:
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Leave modem mode when the USB host goes away, instead of after a fixed timeout.
|
||||
|
||||
Stock firmware dropped out of hotspot mode if the host was quiet for 20 seconds, which
|
||||
made the radio unusable as a permanently attached modem - so that timeout was disabled
|
||||
on request. The side effect was that the radio then stayed a modem forever and had to be
|
||||
power cycled by hand after every test.
|
||||
|
||||
This ties the exit to the actual USB connection state instead: while the host is present
|
||||
the radio stays a modem no matter how quiet it is, and as soon as the cable is pulled (or
|
||||
the host stops enumerating it) the radio returns to normal operation by itself.
|
||||
"""
|
||||
W = "/home/viktor/ogd77rel/uv_src/OpenGD77_MDUV380_DM1701_20260130/MDUV380_firmware/application"
|
||||
p = W + "/source/functions/hotspot.c"
|
||||
s = open(p).read()
|
||||
|
||||
if "usbHostIsAttached" in s:
|
||||
print("already patched")
|
||||
raise SystemExit(0)
|
||||
|
||||
# a small helper next to the other statics
|
||||
anchor = "static const uint32_t MMDVMHOST_TIMEOUT = MMDVMHOST_TIMEOUT_DISABLED;\n"
|
||||
assert anchor in s, "timeout constant not found"
|
||||
|
||||
helper = anchor + """
|
||||
// The USB device handle tells us whether a host is actually enumerating us. Losing that
|
||||
// is what "the computer went away" really means; host silence alone is not.
|
||||
extern USBD_HandleTypeDef hUsbDeviceFS;
|
||||
|
||||
static bool usbHostIsAttached(void)
|
||||
{
|
||||
return (hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED);
|
||||
}
|
||||
"""
|
||||
s = s.replace(anchor, helper, 1)
|
||||
|
||||
# make sure the USB device header is included
|
||||
if '#include "usb_device.h"' not in s:
|
||||
inc_anchor = '#include "functions/ticks.h"\n'
|
||||
assert inc_anchor in s, "include anchor missing"
|
||||
s = s.replace(inc_anchor, inc_anchor + '#include "usb_device.h"\n', 1)
|
||||
|
||||
# both inactivity checks now also fire when the host has disconnected
|
||||
old = """ if ((MMDVMHOST_TIMEOUT != 0) && (nonVolatileSettings.hotspotType == HOTSPOT_TYPE_MMDVM) &&
|
||||
((ticksGetMillis() - mmdvmHostLastActiveTime) > MMDVMHOST_TIMEOUT))
|
||||
"""
|
||||
new = """ if ((nonVolatileSettings.hotspotType == HOTSPOT_TYPE_MMDVM) &&
|
||||
((usbHostIsAttached() == false) ||
|
||||
((MMDVMHOST_TIMEOUT != 0) && ((ticksGetMillis() - mmdvmHostLastActiveTime) > MMDVMHOST_TIMEOUT))))
|
||||
"""
|
||||
count = s.count(old)
|
||||
assert count == 2, "expected 2 inactivity checks, found %d" % count
|
||||
s = s.replace(old, new)
|
||||
|
||||
open(p, "w").write(s)
|
||||
print("hotspot.c: modem mode now ends when the USB host disconnects (%d checks)" % count)
|
||||
Ссылка в новой задаче
Block a user