#!/usr/bin/env python3 """Диагностическая сборка: зеркалит все кадры от DMR-модуля в USB-порт. Перехватывается единственный вызов `fm100b_on_frame` (0x08006348) из разборщика кадров. Наша функция выдаёт в компьютерный порт маркер F1 F2, длину и сам кадр, после чего передаёт управление штатному обработчику — логика радио не меняется. python3 build_sniffer.py # -> stock-fw/rt4d_sniffer.bin python3 tools/flash_ps.py stock-fw/rt4d_sniffer.bin python3 tools/sniff.py 60 # слушать 60 секунд Сборка временная: для обычной работы вернуть stock-fw/rt4d_ru_batt.bin. """ import struct from keystone import Ks, KS_ARCH_ARM, KS_MODE_THUMB BASE = 0x08002800 SRC = "stock-fw/rt4d_ru_batt.bin" OUT = "stock-fw/rt4d_sniffer.bin" ON_FRAME = 0x08006348 # void fm100b_on_frame(u8 *frame) CALL_SITE = 0x08018DD8 # единственный bl на него TX_BYTE = 0x08018BFC # void usart6_tx_byte(u8) — порт к компьютеру def thumb_bl(src, dst): off = (dst - (src + 4)) >> 1 s = (off >> 23) & 1; i1 = (off >> 22) & 1; i2 = (off >> 21) & 1 imm10 = (off >> 11) & 0x3FF; imm11 = off & 0x7FF j1 = (~i1 ^ s) & 1; j2 = (~i2 ^ s) & 1 return struct.pack("> 1 blt = struct.pack("