diff options
| author | info@mode42.com <info@mode42.com> | 2026-08-07 18:25:13 +0000 |
|---|---|---|
| committer | info@mode42.com <info@mode42.com> | 2026-08-07 18:25:13 +0000 |
| commit | 04d965d67a7264a1c7c211494aebda1953df7603 (patch) | |
| tree | 0ebd700a6e219f84a26a656f4bee8778bc75da7b /docs | |
Initial push
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ARCHITECTURE.md | 40 | ||||
| -rw-r--r-- | docs/AX25-NATIVE-CODEC.md | 33 | ||||
| -rw-r--r-- | docs/BAYCOM-FREEZES.md | 40 | ||||
| -rw-r--r-- | docs/BAYCOM.md | 52 | ||||
| -rw-r--r-- | docs/CRDOP.md | 44 | ||||
| -rw-r--r-- | docs/DEV/README.md | 9 | ||||
| -rw-r--r-- | docs/DEV/TMODEM-C1224.md | 40 | ||||
| -rw-r--r-- | docs/DEV/TNC-MODEM-DEV.md | 191 | ||||
| -rw-r--r-- | docs/DEVELOPMENT.md | 38 | ||||
| -rw-r--r-- | docs/FREEBSD-AX25.md | 34 | ||||
| -rw-r--r-- | docs/HARDWARE-ACCEPTANCE.md | 38 | ||||
| -rw-r--r-- | docs/HYBBX.md | 44 | ||||
| -rw-r--r-- | docs/LINUX-HOST-SETUP.md | 48 | ||||
| -rw-r--r-- | docs/MASTER-GUIDE.md | 264 | ||||
| -rw-r--r-- | docs/MAX25-CLIENT.md | 36 | ||||
| -rw-r--r-- | docs/MAX25-OPERATOR-RUNBOOK.md | 105 | ||||
| -rw-r--r-- | docs/MAX25-TERMINAL.md | 95 | ||||
| -rw-r--r-- | docs/MERGE-REPORT.md | 36 | ||||
| -rw-r--r-- | docs/MODULAR-TCPIP-SERVER.md | 33 | ||||
| -rw-r--r-- | docs/NETDEV.md | 27 | ||||
| -rw-r--r-- | docs/PACKET-RADIO.md | 46 | ||||
| -rw-r--r-- | docs/PATHS.md | 46 | ||||
| -rw-r--r-- | docs/PLATFORMS.md | 34 | ||||
| -rw-r--r-- | docs/PLUGINS-DEVICE-MODEL.md | 36 | ||||
| -rw-r--r-- | docs/README.md | 40 | ||||
| -rw-r--r-- | docs/TX-RX-TEST.md | 137 | ||||
| -rw-r--r-- | docs/V1.0.0-SCOPE.md | 42 | ||||
| -rw-r--r-- | docs/V2.0.0-SCOPE.md | 35 | ||||
| -rw-r--r-- | docs/WEBSOCKET.md | 129 |
29 files changed, 1792 insertions, 0 deletions
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..a1dc291 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,40 @@ +# Architecture · MAX25-Stack 1.8.0 + +Main AX.25 Stack — standalone packet-radio with HyBBX-compatible plugin boundaries. + +## Layer model matrix + +| Layer | Examples | +|-------|----------| +| Terminal | `max25-terminal`, `max25-client` | +| Daemon | `max25d` — M25/1, plugin lifecycle | +| Operating mode | `standalone`, `service`, `hybbx-host` | +| Hardware | `tncs`, `modems`, `soft-modems` | +| Device | `tnc2c`, `max25e0`, `soft-crdop` | +| Protocol | KISS, kernel hdlcdrv, CRDOP M25 host | + +## DEV-Level matrix + +| DEV-Level | Focus | +|-----------|-------| +| DEV-Level 1 (current) | Modular TCP/IP, Linux+FreeBSD compat, `max25d0` | +| DEV-Level 2 | Main+Secondary supervision, `max25-tun` | +| DEV-Level 3 | WebSocket gateway | +| DEV-Level 4 | CRDOP expansion | +| Later | AI/assistant — deferred | + +## Platform split matrix + +| Component | Linux | FreeBSD | +|-----------|-------|---------| +| `max25d` + RF (TNC/BayCom) | yes | scaffold | +| `max25-terminal` | yes | yes (remote) | +| CRDOP | ALSA | OSS | +| Kernel BayCom `bcsf0` | yes | no | + +## Related + +| Goal | Doc | +|------|-----| +| Platforms | [PLATFORMS.md](PLATFORMS.md) | +| v2 scope | [V2.0.0-SCOPE.md](V2.0.0-SCOPE.md) | diff --git a/docs/AX25-NATIVE-CODEC.md b/docs/AX25-NATIVE-CODEC.md new file mode 100644 index 0000000..a865e9c --- /dev/null +++ b/docs/AX25-NATIVE-CODEC.md @@ -0,0 +1,33 @@ +# AX.25 native codec · MAX25-Stack 1.8.0 + +In-tree userspace AX.25 encode/decode — no kernel AX.25 required for max25d. + +## Component matrix + +| Module | Role | +|--------|------| +| `ax25_codec.py` | Address encode/decode, FCS | +| `kiss_bridge.py` | KISS frame wrap/unwrap | +| `banlist.py` | Source address ban list | + +## Build matrix + +| Option | Default | Effect | +|--------|---------|--------| +| `MAX25_BUNDLE_AX25` | OFF | Vendored ax25-apps tarballs reference-only | +| In-tree codec | always | Used by max25d and terminal | + +## FCS matrix + +| Direction | Rule | +|-----------|------| +| To TNC (KISS DATA) | FCS stripped | +| From TNC (RX) | FCS validated in codec | +| UI frames | Built in terminal or HyBBX attach path | + +## Related + +| Goal | Doc | +|------|-----| +| Packet radio | [PACKET-RADIO.md](PACKET-RADIO.md) | +| Hardware acceptance | [HARDWARE-ACCEPTANCE.md](HARDWARE-ACCEPTANCE.md) | diff --git a/docs/BAYCOM-FREEZES.md b/docs/BAYCOM-FREEZES.md new file mode 100644 index 0000000..5b63e81 --- /dev/null +++ b/docs/BAYCOM-FREEZES.md @@ -0,0 +1,40 @@ +# BayCom/based — host freeze warning (RX / TX) + +**MAX25-Stack** · **BayCom/based** SER12 class (PC-COM / TCM3105) + +**Status:** BayCom/based is **available · usable** (default build ON). This page documents **freeze risk** on some hosts — especially legacy kernel paths and EMI near interactive desktops. Current product uses userspace **max25-bcpr**. + +> **Warning:** On some hosts (especially interactive desktops), **RX and TX** with BayCom/based PC-COM-class hardware can **hard-freeze** or soft-hang the machine — historically observed with kernel `baycom_ser_fdx`. Treat SQ-open / strong RF / USB HID hubs as risk. + +## Freeze classes + +| Class | Typical trigger | Radio needed? | +|-------|-----------------|---------------| +| **TX / calibrate (legacy kernel)** | `baycom_test calibrate N`, HDLC calibrate ioctl | **No** — observed with radio **off** | +| **RX / RF EMI** | Peer packet TX / strong RF near the PC; USB HID dropout (`EMI?` in `dmesg`) | Over-air RF; can freeze **even if** no modem driver is loaded | +| Soft hang | High UART IRQ bitbang load; brief input/USB stall | Often radio off | + +Kernel `baycom_ser_fdx` / `baycom-pr` was **removed** from this tree (2026-07-18). Do **not** reintroduce calibrate against `bcsf*` on interactive desktops. + +## Forbidden / high risk on interactive desktops + +| Do not | Why | +|--------|-----| +| Load `baycom_ser_fdx` / run calibrate helpers | Instant hard freeze observed on interactive hosts | +| Hot-plug radio/mic cables while any path owns the UART | Freeze risk | +| Leave stack up unattended next to live RF | EMI class | + +## Safer practice (experimental opt-in only) + +| Do | Notes | +|----|--------| +| Prefer a **dedicated / minimal** host when RF is strong | Reduces EMI freeze class on interactive desktops | +| Unplug AF / power radio off when not testing | Reduces EMI class | +| Move keyboard/mouse to motherboard USB ports | Avoid front/shared hubs near RF | + +## Related + +| Topic | Path | +|-------|------| +| BayCom/based status | [BAYCOM.md](BAYCOM.md) | +| Unified TX/RX release test | [TX-RX-TEST.md](TX-RX-TEST.md) · `scripts/tx-rx-test.sh` | diff --git a/docs/BAYCOM.md b/docs/BAYCOM.md new file mode 100644 index 0000000..ed6e334 --- /dev/null +++ b/docs/BAYCOM.md @@ -0,0 +1,52 @@ +# BayCom/based · MAX25-Stack + +Public mark: **BayCom/based**. Product path: **max25-bcpr** (daemon **max25-bcprd**, ctl **max25-bcpr-ctl**). Host device: **`max25e0`** (forks `max25e0:bcN` only). + +## Status: available and usable + +| Fact | Value | +|------|--------| +| Product status | **Available** — shipped operator path with HyBBX co-host | +| Default build | `MAX25_BUILD_MAX25_BCPR=ON` | +| Device id | **`max25e0`** only | +| KISS release | **`/tmp/max25-bcpr/kiss-bc0`** — HyBBX opens after max25d prep | +| Attach modes | `hybbx-host` · `hybbx-main` · `hybbx-cohost` — max25d releases KISS to HyBBX | +| Host addresses | IPv4 `127.0.0.25/8`, IPv6 `::25/128` (defaults; overridable in `max25d.ini`) | +| Kernel path | `baycom_ser_fdx` / `baycom-pr` **removed** — userspace **max25-bcpr** only | + +## Start (with HyBBX co-host) + +```bash +# max25d with mode=hybbx-cohost and [features] max25_bcpr=yes +./scripts/run-max25d.sh +ls -la /tmp/max25-bcpr/kiss-bc0 # KISS PTY after max25-bcpr ready +# then HyBBX with [networks] baycom=yes, device=/tmp/max25-bcpr/kiss-bc0 +``` + +Example INI: `share/max25-bcpr/max25-bcpr.ini.example` · `share/hybbx/hybbx-standalone.ini.example` (HyBBX repo). + +## Operator rules + +| Rule | Detail | +|------|--------| +| RX before TX | Prove RX (Soft-DCD / decode) before live TX | +| Serial ownership | One process per UART — max25d prep then HyBBX attach | +| HyBBX user | Must be in group `dialout` for KISS PTY | + +Development freeze notes: [BAYCOM-FREEZES.md](BAYCOM-FREEZES.md) — not part of normal operator path. + +## Build + +```bash +cmake -B build -DMAX25_BUILD_MAX25_BCPR=ON # default ON in release preset +cmake --build build --target max25-bcprd max25-bcpr-ctl +``` + +## Related + +| Goal | Doc | +|------|-----| +| Device model | [PLUGINS-DEVICE-MODEL.md](PLUGINS-DEVICE-MODEL.md) | +| TX/RX test | [TX-RX-TEST.md](TX-RX-TEST.md) | +| HyBBX attach | HyBBX [docs/BAYCOM.md](../../hyBBX/docs/BAYCOM.md) | +| TNC / modem bring-up | [DEV/TNC-MODEM-DEV.md](DEV/TNC-MODEM-DEV.md) | diff --git a/docs/CRDOP.md b/docs/CRDOP.md new file mode 100644 index 0000000..927f2f2 --- /dev/null +++ b/docs/CRDOP.md @@ -0,0 +1,44 @@ +# CRDOP / MAX25-SoftModem · MAX25-Stack 1.8.0 + +In-house sound-card modem — acoustically AX.25-compatible AFSK. + +## Status matrix + +| Item | Value | +|------|-------| +| Device id | `soft-crdop` | +| Build | `MAX25_BUILD_CRDOP=ON` default | +| Phase | development and test | +| Speed | 1200 bd primary, max 19200 bd | +| Duplex | half and full | +| Audio | ALSA direct — no PulseAudio | + +## Port matrix + +| Port | Role | +|------|------| +| 8515 | control (M25 host protocol) | +| 8516 | data | +| 7325 | max25d M25/1 (operator IPC) | + +## Platform matrix + +| Host | CRDOP role | +|------|------------| +| Linux | RF backend in max25d | +| FreeBSD | primary softmodem path (OSS) | + +## Start matrix + +| Step | Command | +|------|---------| +| Build | `./scripts/build.sh` | +| Start | `max25-ctl start --hardware soft-modems --device soft-crdop` | +| HyBBX | merge `share/hybbx/crdop-host.ini.example` | + +## Related + +| Goal | Doc | +|------|-----| +| Audio architecture | `stacks/crdop/docs/AUDIO-ARCHITECTURE.md` | +| HyBBX | [HYBBX.md](HYBBX.md) | diff --git a/docs/DEV/README.md b/docs/DEV/README.md new file mode 100644 index 0000000..3aa5770 --- /dev/null +++ b/docs/DEV/README.md @@ -0,0 +1,9 @@ +# Development docs · MAX25-Stack + +Pure **development** material lives under `docs/DEV/`. + +Operator-facing / release manuals stay in `docs/` (and README). Full doc rewrite later — until then, put new bring-up / recovery / internal how-to notes here. + +| Doc | Role | +|-----|------| +| [TNC-MODEM-DEV.md](TNC-MODEM-DEV.md) | TNC + BayCom/based KISS bring-up, software-first recovery | diff --git a/docs/DEV/TMODEM-C1224.md b/docs/DEV/TMODEM-C1224.md new file mode 100644 index 0000000..6b40968 --- /dev/null +++ b/docs/DEV/TMODEM-C1224.md @@ -0,0 +1,40 @@ +# T-Modem-c1224 — max25d device (`tmodem`) + +**AS-IS** · prototype · English only. + +## Role + +[T-Modem-c1224](https://github.com/ngteq/T-Modem-c1224) Pico firmware presents **USB CDC KISS** (half-TNC: HDLC on Pico, AFSK on TCM3105-class chip). max25d talks **raw KISS** on `/dev/ttyACM*` — same family as `kiss-raw-serial` / `baycom-kiss` serial path, but **not** BayCom/based and **not** SER12. + +## Enable + +```ini +[features] +tmodem = yes + +[devices] +default = tmodem +tmodem = /dev/ttyACM0 + +[serial.tmodem] +baud = 115200 +line = 8n1 +dtr_rts = no +``` + +Example file: `share/max25/max25d.tmodem.ini.example`. + +## Terminal + +```bash +max25-terminal -d tmodem +# or SET DEVICE tmodem after connect +``` + +## RX before TX + +Any on-air smoke: prove RX (noise / Soft-DCD / decode) before live TX. See `scripts/tx-rx-test.sh` and vault §0.20. + +## HyBBX + +Attach-only via a running max25d with `tmodem` enabled. No T-Modem L1 inside HyBBX. diff --git a/docs/DEV/TNC-MODEM-DEV.md b/docs/DEV/TNC-MODEM-DEV.md new file mode 100644 index 0000000..e547d0f --- /dev/null +++ b/docs/DEV/TNC-MODEM-DEV.md @@ -0,0 +1,191 @@ +# TNC / Modem bring-up · MAX25-Stack + +English bring-up for **TNCs** (HDLC + KISS on host serial) and **BayCom/based** modems (bits↔AFSK + PTT; host owns HDLC). Applies to MAX25-Stack and to any stack that attaches the same hardware classes. + +--- + +## 1. Roles — TNC vs modem + +| Class | What it is | Host owns | Typical face | +|-------|------------|-----------|--------------| +| **TNC** (TNC2C, PK-TNC2, TNC2multi, …) | Firmware does HDLC; host talks **command mode** then **KISS** on UART | Serial lifecycle, recovery, KISS entry | `tnc2c`, `pktnc2`, … | +| **BayCom/based** modem | Board is **modem-only** (TCM3105-class AFSK + PTT) | HDLC, SER12 bit clock, KISS PTY, PTT | **`max25e0`** (bcpr) | +| Soft-modem (CRDOP) | Soundcard AFSK | Audio + soft HDLC | `soft-crdop` | + +```text +TNC path: Radio AF ↔ TNC (HDLC+modem) ↔ UART KISS ↔ host stack +Modem path: Radio AF ↔ BayCom/based chip ↔ SER12 UART ↔ host HDLC (bcpr) ↔ KISS +``` + +Do **not** treat a BayCom/based board as a TNC. Do **not** open the same `/dev/tty*` from two processes. + +--- + +## 2. KISS bring-up (any stack) + +### 2.1 Serial ownership + +| Rule | Why | +|------|-----| +| **One opener** per UART | Dual openers → garbled RX, failed recovery, flaky KISS | +| Hold **DTR+RTS high** while the port is owned | Landolt TNC2C terminal detect needs DTR high at power-on; drop on close → echo-only | +| Match **baud / line** to hardware | Wrong baud → garbage or echo only | + +| Device class (typical) | Baud | Line | Notes | +|------------------------|------|------|-------| +| Landolt TNC2C | **19200** | 8N1 | Not 4800/9600/7E1 | +| PK-TNC2 / many TF boards | **9600** | 8N1 | Profile-dependent | +| BayCom/based SER12 | UART clocked by host SER12 | — | Product path: **max25-bcpr**, not kernel `baycom_ser_fdx` | + +### 2.2 Command sequence (TheFirmware / TNC-2 class) + +| Step | Action | +|------|--------| +| 1 | Free the port (`pkill` stray terminals; one stack owns the fd) | +| 2 | Open UART with DTR+RTS high; settle ~2 s | +| 3 | Reach **terminal / host command mode** (banner / `cmd:`) — see recovery below | +| 4 | Set callsign / radio params as required by firmware | +| 5 | Enter KISS: TheFirmware **ESC `@K`** (`0x1B 40 4B`); legacy TAPR `kiss on` only as fallback | +| 6 | Keep the **same process** owning the port for KISS DATA | + +KISS exit (if needed): `kiss off`, or frame `0xC0 0xFF 0xC0`, or firmware `RESTART`. + +### 2.3 Boot-wait (cold start) + +After mains loss or cold power without DTR, some boards (notably Landolt TNC2C) need **boot-wait with DTR high during power-on**: + +```bash +cd stacks/tncs +./tnc2c-boot-wait.sh /dev/ttyS4 # keep script open; power OFF 10s → ON +# then start the stack immediately so DTR stays high +``` + +Quiet AF / closed squelch (CD off) during boot improves banner reliability. + +--- + +## 3. Power-cycle history — and the correct path + +| Era | Practice | Status | +|-----|----------|--------| +| Former | Power-cycle + boot-wait for almost every KISS/host recovery | Still valid as **rescue** | +| Root cause (hardware) | Landolt: DTR must be high **at** power-on; late open → echo/transparent | Not fully soft-fixable | +| Root cause (host) | Recovery answers lost if an RX thread races the drain; no escalation to boot-wait | Fixed / mitigated in product recovery path | +| Correct default | **Software recovery ladder first**; power-cycle only if echo-only after ladder | Prefer `tnc_serial_recovery` / `tnc2c-host-reset` | + +### Software-first ladder (summary) + +1. DTR+RTS high, passive listen +2. KISS return `0xC0 0xFF 0xC0` +3. JHOST 0 flush (`^Q^X` + nulls + `JHOST 0`) +4. ESC `V` / ESC `QRES` (software cold boot; DTR stays high) +5. Legacy `kiss off` + `INFO` (last resort) +6. KISS entry ESC `@K` + +Success markers: `TheFirmware`, `NORD`, `Version 2.7`, `Checksum`, `cmd:`. + +| If… | Then… | +|-----|--------| +| Ladder fails → echo only | `./tnc2c-boot-wait.sh` + power OFF→ON with DTR held | +| Standalone reset OK, stack FAIL | Check dual openers / RX race / start order | +| After boot-wait | Start stack **immediately** (avoid DTR drop gap) | + +Detail: `stacks/tncs/docs/TNC-RECOVERY.md`. + +--- + +## 4. Common failure modes + +| Symptom | Likely cause | Fix | +|---------|--------------|-----| +| Garbage / no banner | Wrong baud or 7E1 | Match profile (e.g. TNC2C **19200 8N1**) | +| Echo only (`INFO`→`INFO`) | No terminal mode; DTR missed at power-on | Recovery ladder → else boot-wait + power-cycle | +| Binary noise, no commands | Stuck in KISS | KISS return frame or `kiss off` | +| Intermittent recovery | Second process on same tty | One owner; kill minicom/`fuser` | +| Silent TX after good session (modem) | **Stale KISS PTY** (max25-bcprd recycled outside max25d) | Restart **max25d only** (`auto_start` owns max25-bcprd) | +| TX blocked with Soft-DCD busy | `fulldup=no` + Soft-DCD holds channel | Bench: `fulldup=yes`; production CSMA prove-out later | +| Closed squelch ≠ TX fail | No RX noise does not prove PTT failure | Separate MCR/keying from mic wiring | + +--- + +## 5. MAX25-Stack + +### 5.1 Paths + +| Path | Role | +|------|------| +| **TNC** | `stacks/tncs/` · devices `tnc2c` / `pktnc2` / … · KISS-serial backend | +| **BayCom/based** | `stacks/max25-bcpr/` · `[features] max25_bcpr=yes` · device **`max25e0`** | +| **CRDOP** | `stacks/crdop/` · soft-modem (out of scope here beyond role table) | + +### 5.2 Device face `max25e0` + +| Surface | Name | +|---------|------| +| Product device id | **`max25e0`** | +| INI mapping | `max25e0 = max25-bcpr:bc0` (right side = **backend:port tag**, not product id) | +| Multi-dev | Always forks **`max25e0:bcN`** | +| Forbidden ids | `bcpr`, `bcpr-bc0`, `bcpr-bc1`, any `bcpr-*` as product face | +| `max25e*` family | **MAX25-Stack only** | + +### 5.3 Start + +```bash +# Feature (site or ./local — never commit live secrets) +# [features] +# max25_bcpr = yes +# +# [devices] +# max25e0 = max25-bcpr:bc0 + +./scripts/run-max25d.sh # escalates root only when ttyS/USB/SER12 needs it +./scripts/run-max25-terminal.sh -U /run/max25/modem.sock +``` + +| Rule | Value | +|------|-------| +| Preferred ownership | **max25d** starts/stops max25-bcprd (`auto_start`) | +| Do not | Recycle `max25-bcprd` under a live max25d (stale PTY) | +| Root | **Only when necessary** (SER12 / ioperm / `/dev/port` / ttyS bind) — TCP/unix-only may stay unprivileged | +| Drop | After privileged init, drop to `[daemon] user=` / `group=` when set | + +Site INI examples: `/etc/max25/max25d.ini`, `/etc/max25/max25-bcpr.ini`. Tree secrets: `./local/`. + +### 5.4 RX before TX (live RF) + +Prove **RX** before live **`--tx`** / on-air SEND: + +| Class | RX proof | +|-------|----------| +| BayCom/based | Soft-DCD / noise activity or decoded KISS RX | +| TNC | CONNECT + STATUS (RX ready) before SEND | +| Offline L0 | Encode/decode without PTT — allowed | + +`--force-tx` is debug-only. See [TX-RX-TEST.md](docs/TX-RX-TEST.md). + +### 5.5 Minimal matrices (no duplication) + +| Goal | Doc | +|------|-----| +| Day-to-day ops | [MAX25-OPERATOR-RUNBOOK.md](docs/MAX25-OPERATOR-RUNBOOK.md) | +| BayCom/based / bcpr | [BAYCOM.md](docs/BAYCOM.md) · [BAYCOM-FREEZES.md](docs/BAYCOM-FREEZES.md) | +| Linear operator guide | [MASTER-GUIDE.md](docs/MASTER-GUIDE.md) | +| TNC software recovery | [stacks/tncs/docs/TNC-RECOVERY.md](stacks/tncs/docs/TNC-RECOVERY.md) | +| Device model | [PLUGINS-DEVICE-MODEL.md](docs/PLUGINS-DEVICE-MODEL.md) | +| Doc index | [docs/README.md](docs/README.md) | + +--- + +## 6. Quick decision tree + +```text +Need KISS on a UART TNC? +├─ Port free + correct baud? +│ └─ no → fix ownership / baud +├─ Terminal / cmd: present? +│ ├─ no → software recovery ladder +│ │ └─ still echo only → boot-wait + power-cycle (DTR high) +│ └─ yes → ESC @K (or profile kiss entry) → keep one owner +└─ BayCom/based? + └─ [features] max25_bcpr=yes · max25e0 · run-max25d.sh · RX proof → then TX +``` diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..4a602ea --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,38 @@ +# Development · MAX25-Stack 1.8.0 + +Contributor build, test, and repository layout. + +## Workflow matrix + +| Step | Command | +|------|---------| +| Build | `./scripts/build.sh` | +| Test | `./scripts/test.sh` | +| Release check | `./scripts/release-check.sh` | +| Plugin discovery | `./scripts/discover-plugins.sh --json` | + +## CMake matrix + +| Option | Default | +|--------|---------| +| `MAX25_BUILD_CRDOP` | ON | +| `MAX25_BUNDLE_AX25` | OFF | + +## Layout matrix + +| Path | Content | +|------|---------| +| `stacks/daemon/` | max25d | +| `stacks/terminal/` | max25-terminal | +| `stacks/tncs/` | TNC tools | +| `stacks/max25-bcpr/` | BayCom/based userspace SER12 (bcpr) | +| `stacks/crdop/` | SoftModem | +| `plugins/` | manifest + betriebsform | +| `share/` | INI examples | + +## Related + +| Goal | Doc | +|------|-----| +| Paths | [PATHS.md](PATHS.md) | +| Architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | diff --git a/docs/FREEBSD-AX25.md b/docs/FREEBSD-AX25.md new file mode 100644 index 0000000..eb762e7 --- /dev/null +++ b/docs/FREEBSD-AX25.md @@ -0,0 +1,34 @@ +# FreeBSD AX.25 port · MAX25-Stack 1.8.0 + +FreeBSD platform plan — no native kernel AX.25; userspace KISS/M25/1 only. + +## Platform matrix + +| Component | FreeBSD | +|-----------|---------| +| `max25d` + TNC/BayCom RF | scaffold (Linux-first v1) | +| `max25-terminal` | yes — remote to Linux `:7325` | +| CRDOP / OSS | yes — primary softmodem path | +| Kernel BayCom | no | + +## Split deployment matrix + +| Role | Typical host | +|------|--------------| +| FreeBSD Main | TCP/IP hub + CRDOP | +| Linux Secondary | TNC / BayCom RF backend | + +## Scaffold matrix (v1.8.0) + +| Item | Path | +|------|------| +| Platform detection | `max25_platform.py` | +| OSS sound-proxy | CRDOP stack | +| INI example | `share/max25/max25d.freebsd.ini.example` | + +## Related + +| Goal | Doc | +|------|-----| +| Platforms | [PLATFORMS.md](PLATFORMS.md) | +| CRDOP | [CRDOP.md](CRDOP.md) | diff --git a/docs/HARDWARE-ACCEPTANCE.md b/docs/HARDWARE-ACCEPTANCE.md new file mode 100644 index 0000000..3d329b8 --- /dev/null +++ b/docs/HARDWARE-ACCEPTANCE.md @@ -0,0 +1,38 @@ +# Hardware acceptance · MAX25-Stack 1.8.0 + +Manual RF acceptance criteria for release tagging. + +## Smoke test matrix + +| Device | Pass criterion | +|--------|----------------| +| `tnc2c` | UART boot-wait + KISS + decode at remote | +| `max25e0` | bcpr SER12 + PTT + on-air | +| `soft-crdop` | ALSA loopback or acoustic bench (optional for tag) | + +## Offline test matrix + +| Test | Scope | +|------|-------| +| `release-check.sh` | repo consistency | +| `scripts/tx-rx-test.sh` (L0) | TX/RX host paths — TNC + BayCom/based (bcpr) | +| `test_crdop_backend.py` | CRDOP backend | +| `test_bell202_line_code.py` | modem line code | +| `max25_test` target | offline smoke (includes `max25_tx_rx_test`) | + +Live TX/RX (`--live` / `--tx`): see [TX-RX-TEST.md](TX-RX-TEST.md) — not CI. + +## Blocker matrix + +| Gate | v1.8.0 status | +|------|---------------| +| CI offline gates | pass target | +| Manual TNC RF | operator pending | +| Manual BayCom RF | operator pending | + +## Related + +| Goal | Doc | +|------|-----| +| Release readiness | [../RELEASE-READINESS.md](../RELEASE-READINESS.md) | +| v1 scope | [V1.0.0-SCOPE.md](V1.0.0-SCOPE.md) | diff --git a/docs/HYBBX.md b/docs/HYBBX.md new file mode 100644 index 0000000..4772d5f --- /dev/null +++ b/docs/HYBBX.md @@ -0,0 +1,44 @@ +# HyBBX integration · MAX25-Stack 1.8.0 + +MAX25 is the standalone RF/link layer — HyBBX consumes via transport plugins after MAX25 prep. + +## Plugin mapping matrix + +| MAX25 hardware | HyBBX plugin | INI `[networks]` | +|----------------|--------------|------------------| +| `hardware/tncs` | `packet_radio` | `ax25=yes` | +| `hardware/modems` | `baycom` | `baycom=yes` | +| `hardware/soft-modems` | `crdop` | `crdop=yes` | + +## Order rule matrix + +| Rule | Detail | +|------|--------| +| Start order | MAX25 before HyBBX | +| Serial ownership | One process per port | +| v2.4.0 HyBBX | `[max25] check=yes`, `kiss_entry=none` | +| BayCom in packet_radio | rejected — use MAX25 + baycom plugin | + +## TNC workflow matrix + +| Step | Action | +|------|--------| +| 1 | `max25-ctl start --hardware tncs --device tnc2c` | +| 2 | Merge `share/hybbx/tnc2c-host.ini.example` | +| 3 | HyBBX `[max25] check=yes`, `kiss_entry=none` | +| 4 | Start HyBBX Secondary → HBX to Main | + +## INI fragment matrix + +| Device | Example INI | +|--------|-------------| +| TNC2C | `share/hybbx/tnc2c-host.ini.example` | +| BayCom/based | via MAX25 **bcpr** (kernel SER12 host INI removed) | +| CRDOP | `share/hybbx/crdop-host.ini.example` | + +## Related + +| Goal | Doc | +|------|-----| +| Packet radio facts | [PACKET-RADIO.md](PACKET-RADIO.md) | +| BayCom | [BAYCOM.md](BAYCOM.md) | diff --git a/docs/LINUX-HOST-SETUP.md b/docs/LINUX-HOST-SETUP.md new file mode 100644 index 0000000..5f3ada9 --- /dev/null +++ b/docs/LINUX-HOST-SETUP.md @@ -0,0 +1,48 @@ +# Linux host setup · MAX25-Stack 1.8.0 + +Example settings for running `max25d` on a Linux host with USB TNC or sound-card modem. + +## Component matrix + +| Component | On Linux | Notes | +|-----------|----------|-------| +| `max25d` | yes | Python 3 | +| `max25-terminal` | yes | Unix socket or `127.0.0.1:7325` | +| TNC2C / USB TNC | yes | `/dev/ttyUSB*` | +| BayCom/based (SER12) | yes | `max25-bcpr` default ON; KISS `/tmp/max25-bcpr/kiss-bc0` | +| CRDOP | yes | ALSA sound device | +| HyBBX attach | yes | after MAX25 prep | + +## Dependency matrix (Debian/Ubuntu) + +| Package group | Packages | +|---------------|----------| +| Build | `build-essential`, `cmake`, `pkg-config`, `git` | +| Runtime | `python3`, `libncurses-dev` | +| CRDOP | `libasound2-dev` | +| BayCom/based | built with default stack | Real 8250 UART; prove RX before TX | + +## Install matrix + +| Step | Command | +|------|---------| +| Build | `./scripts/build.sh` | +| INI deploy | copy `share/max25/max25d.ini.host.example` → site config | +| Run daemon | `max25d -c /etc/max25/max25d.ini` | +| Terminal | `max25-terminal -U /run/max25/modem.sock --ax25-ui` | +| Serial access | `usermod -aG dialout $USER` | + +## Config matrix + +| Item | Value | +|------|-------| +| Live INI | site path or `./local/max25d.ini` | +| M25/1 port | `7325` | +| Secrets | `./local/` only | + +## Related + +| Goal | Doc | +|------|-----| +| Operator runbook | [MAX25-OPERATOR-RUNBOOK.md](MAX25-OPERATOR-RUNBOOK.md) | +| HyBBX | [HYBBX.md](HYBBX.md) | diff --git a/docs/MASTER-GUIDE.md b/docs/MASTER-GUIDE.md new file mode 100644 index 0000000..17a395d --- /dev/null +++ b/docs/MASTER-GUIDE.md @@ -0,0 +1,264 @@ +<!-- AUTO-SYNC 2026-08-01 — vault: projects/max25-stack/2026-07-13-master-documentation.md --> +<!-- Re-sync: /home/akb/Code/0-RESEARCHES/tools/vault-sync-slave-docs.sh --> + +# MAX25-Stack — Master operator guide + +**Shipped guide** — canonical edits in research vault `projects/max25-stack/2026-07-13-master-documentation.md`; run sync script after change. + +## Summary + +Single linear guide: MAX25 layer model, `max25d`, devices (TNC, BayCom, CRDOP), M25/1 protocol, TNC recovery, FreeBSD split, HyBBX boundary. Shipped docs in `docs/` and `stacks/tncs/docs/` remain **frozen reference**. + +--- + +## 1. What MAX25 is + +**Main AX.25 Stack (MAX25)** — standalone packet-radio stack with HyBBX-compatible plugin boundaries. Owns RF prep (boot-wait, KISS entry, BayCom kernel lifecycle, CRDOP audio). HyBBX consumes prepared devices via transport plugins. + +``` +max25-terminal / max25-client (F10 menu, M25/1) + │ +max25d — Main + Secondaries (:7325 M25/1) + │ +HyBBX (external) — packet_radio | baycom | crdop + │ +Hardware — tnc2c | baycom-ser12 | soft-crdop +``` + +Frozen: `docs/ARCHITECTURE.md`, `docs/README.md`. + +--- + +## 2. Host layout — Main + Secondaries + +| Role | Count | Function | +|------|-------|----------| +| **Main** | 1× | Stack hub, HyBBX attach point, M25/1 `:7325` | +| **Secondary** | 0–5+ | Additional `max25d` instances — one RF backend each | + +**Linux rules (when netdev ships):** + +| Item | Name | +|------|------| +| TUN interface | **`max25d0`** only | +| BayCom kernel netdev | **`bcsf0`** unchanged | + +**Example split:** FreeBSD Main (CRDOP/TCP/IP hub) + Linux Secondary (TNC/BayCom). Not mandatory — single Linux host is the primary v1 layout. + +Vault matrix: [2026-07-13-max25-freebsd-tnc-baycom-full-feature-matrix.md](2026-07-13-max25-freebsd-tnc-baycom-full-feature-matrix.md). + +--- + +## 3. Install and site configuration + +```bash +git clone <repo> MAX25-Stack && cd MAX25-Stack +./scripts/build.sh +sudo cmake --install build --prefix /usr/local # or user prefix +``` + +| File | Purpose | +|------|---------| +| `~/.config/max25/max25d.ini` | Devices, TCP, auth, serial watch | +| `share/max25/max25d.ini.example` | Template | +| `share/hybbx/*-host.ini.example` | HyBBX attach fragments | + +```ini +[devices] +tnc2c = serial:/dev/ttyUSB0 +; soft-crdop = crdop:default +``` + +Frozen runbook: `docs/MAX25-OPERATOR-RUNBOOK.md`, `docs/LINUX-HOST-SETUP.md`. + +--- + +## 4. Start stack — by device type + +### TNC (tnc2c, pktnc2) + +```bash +max25-ctl start --hardware tncs --device tnc2c +# or: stacks/tncs/tnc2c-boot-wait.sh +``` + +Boot-wait: DTR+RTS high during power-on (Landolt TNC2C). Software recovery ladder before power cycle. + +### BayCom/based (max25-bcpr userspace SER12) + +**Available and usable** — default build ON (`MAX25_BUILD_MAX25_BCPR=ON`). Device **`max25e0`**. KISS release **`/tmp/max25-bcpr/kiss-bc0`**. + +```bash +max25-ctl start --mode hybbx-cohost # or hybbx-host / standalone +# max25-bcpr-ctl when running daemon directly +``` + +HyBBX attach: `[networks] baycom=yes` · `[transport.baycom1] device=/tmp/max25-bcpr/kiss-bc0`. + +SSoT: [2026-08-01-baycom-pccom-operational-status.md](../integration/2026-08-01-baycom-pccom-operational-status.md) · [cohost runbook](../integration/2026-07-31-standalone-cohost-runbook.md). + +Legacy kernel path (`baycom-pr` / `baycom_ser_fdx`) — removed from product; freeze notes in shipped `docs/BAYCOM-FREEZES.md` only. + +### CRDOP (soft modem) + +```bash +max25-ctl start --hardware soft-modems --device soft-crdop +# TCP 8515 (control) / 8516 (data) +``` + +Vault dev master: [2026-07-13-crdop-development-master.md](2026-07-13-crdop-development-master.md). + +Verify: `max25-ctl status` · `ss -ltn | grep 7325`. + +--- + +## 5. M25/1 and operator terminal + +| Item | Value | +|------|-------| +| Protocol | M25/1 text commands on TCP `:7325` | +| Client | `max25-terminal` — `SET DEVICE`, `CONNECT`, `SEND` | +| Codec | In-tree `ax25_codec.py` — no kernel AX.25 required | + +Frozen: `docs/MAX25-TERMINAL.md`, `include/max25/protocol.md`. + +--- + +## 6. TNC recovery (software-first) + +Power cycle is **rescue fallback** only when DTR was low at cold boot or hardware hang. + +| Situation | First action | +|-----------|--------------| +| Echo-only (`INFO` → `INFO`) | `tnc2c-host-reset.sh` or max25d serial watch | +| After prep `error-host` | Auto boot-wait escalate (if enabled) | +| Cold boot, no `cmd:` | `tnc2c-boot-wait.sh` with DTR before power-on | + +**Software ladder** (TheFirmware TF 2.7): KISS return → JHOST 0 → ESC V → ESC QRES → ESC `@K` → MYCALL. + +| Layer | Responsibility | +|-------|----------------| +| `max25d` / boot-wait | DTR, recovery, `kiss on`, serial watch | +| HyBBX `packet_radio` | Attach only — `kiss_entry=none` | + +Vault SSoT: [2026-07-13-thefirmware-native-recovery-sequence.md](2026-07-13-thefirmware-native-recovery-sequence.md) · [hardware/tnc2c/2026-07-13-kiss-host-without-power-cycle.md](../../hardware/tnc2c/2026-07-13-kiss-host-without-power-cycle.md). + +max25d INI defaults: `serial_watch=yes`, `stack_recover_only=yes`, `serial_bootwait_escalate=yes`. + +Known failure mode (power-cycle still required): [2026-07-13-max25d-tnc-recovery-power-cycle-root-cause.md](2026-07-13-max25d-tnc-recovery-power-cycle-root-cause.md). + +Frozen: `MAX25-Stack/stacks/tncs/docs/TNC-RECOVERY.md`. + +--- + +## 7. BayCom/based ↔ max25d + +``` +Radio ← UART ← max25-bcprd (userspace SER12+HDLC) ← KISS PTY /tmp/max25-bcpr/kiss-bc0 ← HyBBX baycom / max25d +``` + +| Fact | Value | +|------|--------| +| Ship status | **Available · usable** — default build ON | +| Device id | **`max25e0`** (forks `max25e0:bcN`) | +| HyBBX cohost | `mode=hybbx-cohost` · verified standalone Main co-host 2026-07-31 / 2026-08-01 | +| RX before TX | Prove decode before live TX — [RX rule](../../operations/2026-07-19-rx-before-tx-rule.md) | + +| Use BayCom/based when | Use TNC when | +|-----------------------|--------------| +| PC-COM / SER12 on real 8250 UART | TNC2C, PK-TNC2, USB serial KISS | +| max25-bcpr userspace path | Boot-wait + firmware KISS | + +Alias compatibility: [2026-07-13-baycom-max25d-alias-compatibility.md](2026-07-13-baycom-max25d-alias-compatibility.md). + +Shipped: `docs/BAYCOM.md` · vault SSoT: [2026-08-01-baycom-pccom-operational-status.md](../integration/2026-08-01-baycom-pccom-operational-status.md). + +--- + +## 8. CRDOP + +MAX25-SoftModem (`soft-crdop`) — acoustic AX.25 over soundcard. FreeBSD uses OSS; Linux uses ALSA. + +| Host | CRDOP role | +|------|------------| +| Linux | RF backend in `max25d` | +| FreeBSD | Primary softmodem path (no kernel BayCom/TNC in stack defaults) | + +**Upstream (operator · 2026-07-25):** modulation development on **T-Modem-384b** HW → **soft import** into this MAX25 soft path (**no** HW modem IC on MAX25). HyBBX boundary unchanged. SSoT: [384b identity § flow](../../operations/2026-07-25-t-modem-384b-identity.md#development-flow-operator--2026-07-25) · [CRDOP master](2026-07-13-crdop-development-master.md). + +Frozen: `docs/CRDOP.md`, `stacks/crdop/docs/`. + +--- + +## 9. FreeBSD and platform split + +| Component | Linux | FreeBSD | +|-----------|-------|---------| +| `max25d` + RF (TNC/BayCom) | ✅ | ❌ (daemon Linux-first in v1) | +| `max25-terminal` | ✅ | ✅ (remote to Linux `:7325`) | +| CRDOP standalone / OSS | ALSA | OSS (DEV-Level 1 port) | +| Kernel BayCom `bcsf0` | ✅ | ❌ | + +No native FreeBSD kernel AX.25 — userspace KISS/M25/1 only. Vault: [2026-07-13-max25-freebsd-tnc-baycom-full-feature-matrix.md](2026-07-13-max25-freebsd-tnc-baycom-full-feature-matrix.md). + +Frozen: `docs/FREEBSD-AX25.md`, `docs/PLATFORMS.md`. + +--- + +## 10. HyBBX boundary + +**MAX25 before HyBBX.** One serial owner per port. + +| MAX25 owns | HyBBX owns | +|------------|------------| +| Boot-wait, MYCALL, `kiss on`, max25-bcpr prep, CRDOPC | `[max25] check`, KISS attach, AX.25 UI, HBX, broadcast | + +```bash +max25-ctl start --hardware tncs --device tnc2c # 1 +ss -ltn | grep 7325 # 2 +hybbxd -c hybbx.ini # 3 — kiss_entry=none +``` + +Vault: [../integration/2026-07-12-max25-hybbx-boundary-final.md](../integration/2026-07-12-max25-hybbx-boundary-final.md). + +Frozen: `docs/HYBBX.md`, `docs/PACKET-RADIO.md`. + +--- + +## 11. Virtual netdev (planned) + +TUN **`max25d0`** — IPv4 `127.0.0.25/8`, IPv6 `::25/128`. DEV-Level 1 scaffold; `[netdev] enabled=no` default. + +Vault analysis: [2026-07-13-max25-tcpip-virtual-netdev-hbx-analysis.md](2026-07-13-max25-tcpip-virtual-netdev-hbx-analysis.md). + +Frozen: `docs/NETDEV.md`. + +--- + +## 12. Troubleshooting + +| Symptom | Check | +|---------|-------| +| Serial busy | One owner — stop minicom; max25d **or** HyBBX | +| TNC silent / echo-only | Recovery ladder; DTR at boot | +| max25d unreachable | HyBBX skips local TNC when `[max25] check=yes` | +| BayCom KISS open failed (io) | KISS path `/tmp/max25-bcpr/kiss-bc0`; max25d `mode=hybbx-cohost`; HyBBX in `dialout` — [root-cause](../integration/2026-07-31-baycom-kiss-open-io-root-cause.md) | +| CRDOP TCP fail | Ports 8515/8516; `crdopc` running | + +Release audit: [2026-07-12-max25-v1.0.0-release-audit.md](2026-07-12-max25-v1.0.0-release-audit.md). + +--- + +## Related + +| Topic | Path | +|-------|------| +| FreeBSD + feature matrix SSoT | [2026-07-13-max25-freebsd-tnc-baycom-full-feature-matrix.md](2026-07-13-max25-freebsd-tnc-baycom-full-feature-matrix.md) | +| TF native recovery SSoT | [2026-07-13-thefirmware-native-recovery-sequence.md](2026-07-13-thefirmware-native-recovery-sequence.md) | +| max25d power-cycle root cause | [2026-07-13-max25d-tnc-recovery-power-cycle-root-cause.md](2026-07-13-max25d-tnc-recovery-power-cycle-root-cause.md) | +| CRDOP development | [2026-07-13-crdop-development-master.md](2026-07-13-crdop-development-master.md) | +| HyBBX integration guide | [../hybbx/2026-07-13-master-documentation.md](../hybbx/2026-07-13-master-documentation.md) | +| Dual-TNC operator flow | [DUAL-TNC-OPERATOR-GUIDE.md](DUAL-TNC-OPERATOR-GUIDE.md) | +| TNC2multi integration | [2026-07-14-tnc2multi-max25-integration.md](2026-07-14-tnc2multi-max25-integration.md) | +| Linux kernel AX.25 ecosystem gap | [reference/2026-07-13-linux-kernel-ax25-ecosystem-gap.md](../../reference/2026-07-13-linux-kernel-ax25-ecosystem-gap.md) | +| Frozen product docs | `docs/`, `stacks/tncs/docs/` | diff --git a/docs/MAX25-CLIENT.md b/docs/MAX25-CLIENT.md new file mode 100644 index 0000000..65ba453 --- /dev/null +++ b/docs/MAX25-CLIENT.md @@ -0,0 +1,36 @@ +# max25-client / M25/1 · MAX25-Stack 1.8.0 + +M25/1 text protocol reference for client developers. + +## Protocol matrix + +| Item | Value | +|------|-------| +| Transport | TCP `:7325` or Unix socket | +| Framing | line-oriented text commands | +| Spec | `include/max25/protocol.md` | +| Codec | in-tree — no kernel AX.25 required | + +## Session matrix + +| Phase | Commands | +|-------|----------| +| Select device | `SET DEVICE`, `LIST DEVICES` | +| Connect | `CONNECT`, `DISCONNECT` | +| Transfer | `SEND`, status queries | +| Ban list | `BAN`, `UNBAN`, `BANS` | + +## Client profile matrix + +| Item | Path | +|------|------| +| Profiles | `share/clients/` | +| Index | `share/clients/index.yaml` | +| Official client | `max25-terminal` only | + +## Related + +| Goal | Doc | +|------|-----| +| Terminal operator | [MAX25-TERMINAL.md](MAX25-TERMINAL.md) | +| Architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | diff --git a/docs/MAX25-OPERATOR-RUNBOOK.md b/docs/MAX25-OPERATOR-RUNBOOK.md new file mode 100644 index 0000000..dd53b24 --- /dev/null +++ b/docs/MAX25-OPERATOR-RUNBOOK.md @@ -0,0 +1,105 @@ +# Operator runbook · MAX25-Stack + +Day-to-day operator procedures for max25d and RF backends. + +Public mark for SER12/PC-COM class: **BayCom/based**. Product path: **max25-bcpr** (available · default build ON). Never **Konverter** / **converter**. + +## Canonical paths + +| Component | Path / command | +|-----------|----------------| +| Daemon | **`./scripts/run-max25d.sh`** · `stacks/daemon/max25d` · `/usr/local/bin/max25d` | +| Terminal | **`./scripts/run-max25-terminal.sh`** · `/usr/local/bin/max25-terminal` · `build*/bin/…` | +| max25-bcpr-ctl | `stacks/max25-bcpr/tools/max25-bcpr-ctl` or `/usr/local/sbin/max25-bcpr-ctl` | +| TX/RX test | `scripts/tx-rx-test.sh` | +| Site INI | `/etc/max25/max25d.ini` · `/etc/max25/max25-bcpr.ini` | +| Tree INI | `local/max25d.ini` (gitignored) | +| KISS PTY | `/tmp/max25-bcpr/kiss-bc0` (from bcpr.ini `kiss_link`) | +| Unix sock | `/run/max25/modem.sock` | + +**Never** `stacks/daemon/max25-terminal` (does not exist). +**Never** trust a leftover ELF at `stacks/terminal/max25-terminal` — use the launcher or PATH (`--help` must list `-d, --device`). + +## Daily workflow (BayCom/based · bcpr) + +```bash +cd /home/akb/Code/10-PROJECTS/MAX25-Stack # or your clone + +# 1) daemon (owns max25-bcprd when auto_start=yes) — needs socket dir +sudo mkdir -p /run/max25 +sudo ./scripts/run-max25d.sh # uses local/max25d.ini or /etc/max25/max25d.ini +# wait for: raw KISS open /tmp/max25-bcpr/kiss-bc0 + +# 2) terminal (checks socket; picks binary with -d) +./scripts/run-max25-terminal.sh -U /run/max25/modem.sock +# CONNECT (F10→6) → SEND … +``` + +`connect failed` ⇒ max25d not running (no `/run/max25/modem.sock`). Start step 1 first. + +Manual bcpr (only when debugging without max25d): + +```bash +sudo ./stacks/max25-bcpr/tools/max25-bcpr-ctl -c /etc/max25/max25-bcpr.ini preflight +sudo ./stacks/max25-bcpr/tools/max25-bcpr-ctl -c /etc/max25/max25-bcpr.ini start +sudo ./stacks/max25-bcpr/tools/max25-bcpr-ctl -c /etc/max25/max25-bcpr.ini status +``` + +## Device start matrix + +| Device | Command | +|--------|---------| +| TNC2C | `max25-ctl start --hardware tncs --device tnc2c` | +| BayCom/based | max25d `[features] max25_bcpr=yes` · device `max25e0` — see [BAYCOM.md](BAYCOM.md) | +| CRDOP | `max25-ctl start --hardware soft-modems --device soft-crdop` | + +## TX prove-out + +| Path | Command | +|------|---------| +| Unified | `sudo ./scripts/tx-rx-test.sh --device modem --live --tx --tx-seconds 3 -c /etc/max25/max25-bcpr.ini` | +| max25-bcpr smoke | `sudo ./stacks/max25-bcpr/tools/max25-bcpr-ctl -c /etc/max25/max25-bcpr.ini smoke --live --tx --tx-seconds 3` | +| Terminal | `./scripts/run-max25-terminal.sh -U /run/max25/modem.sock` → CONNECT → SEND | + +Details: [TX-RX-TEST.md](TX-RX-TEST.md). + +### TX path matrix (Zentralnerv) + +| Trigger | Host MCR (~3s) | Notes | +|---------|----------------|-------| +| Long KISS → `/tmp/max25-bcpr/kiss-bc0` (info ≈376B, slave held open) | Yes | Proven RF when LED/wattmeter watched | +| `max25-bcpr-rxtx-smoke` / `tx-rx-test` L4 `--tx --tx-seconds 3` | Yes | Requires MCR `0xe`/`0xf` for PASS | +| max25d unix/terminal `SEND` | Yes (shorter if payload ≤256B ≈2.2s) | Keep PTY open (max25d); do not recycle max25-bcprd outside max25d | +| open/write/**close** KISS without hold | No / intermittent | POLLHUP race — fixed in max25-bcprd (POLLIN before HUP) | +| Stale max25d FD after external max25-bcprd restart | No | Restart **max25d** only | + +Operator RF evidence (optional, not CI): radio **TX/PTT LED** + **external** wattmeter needle. + +**2026-07-19:** Operator confirmed RF on AX25WRK1 (TX LED / external wattmeter) during live prove-out. + +## Recovery matrix + +| Situation | First action | +|-----------|--------------| +| Echo-only TNC | `tnc2c-host-reset.sh` or serial watch | +| After crash | boot-wait escalate if enabled | +| Cold boot no `cmd:` | `tnc2c-boot-wait.sh` with DTR before power-on | +| Power cycle | rescue fallback only | +| Stale max25-bcpr KISS | restart **max25d** only (do not recycle max25-bcprd outside max25d) | + +## Status matrix + +| Check | Command | +|-------|---------| +| Daemon | `max25-ctl status` / `ss -ltn \| grep 7325` | +| max25-bcpr | `sudo max25-bcpr-ctl -c /etc/max25/max25-bcpr.ini status` | +| Logs | max25d stdout / site log path | + +## Related + +| Goal | Doc | +|------|-----| +| Linux setup | [LINUX-HOST-SETUP.md](LINUX-HOST-SETUP.md) | +| Terminal | [MAX25-TERMINAL.md](MAX25-TERMINAL.md) | +| BayCom/based | [BAYCOM.md](BAYCOM.md) | +| TNC recovery | `stacks/tncs/docs/TNC-RECOVERY.md` | diff --git a/docs/MAX25-TERMINAL.md b/docs/MAX25-TERMINAL.md new file mode 100644 index 0000000..86d2a22 --- /dev/null +++ b/docs/MAX25-TERMINAL.md @@ -0,0 +1,95 @@ +# max25-terminal · MAX25-Stack + +Sole official operator client — text lines + F10 menu over M25/1. + +## Canonical binary + +| Path | Role | +|------|------| +| `/usr/local/bin/max25-terminal` | Install / PATH — **prefer** | +| `build*/bin/max25-terminal` | CMake output | +| `stacks/terminal/max25-terminal` | Tree copy after build (optional) | + +**Never** `stacks/daemon/max25-terminal` — that path does not exist (daemon is `stacks/daemon/max25d`). + +```bash +max25-terminal --help +# lists: -H -p -U -d/--device -v --probe … +``` + +`-d` / `--device` is **optional**: with max25d `[devices] default = max25e0`, the session already starts on that id. Use `-d` only to override, or type `SET DEVICE <id>` / F10 → **7**. + +## Canonical connect (BayCom/based · bcpr) + +```bash +# max25d already up (auto_start owns max25-bcprd) +max25-terminal -U /run/max25/modem.sock +# header DEVICE: max25e0 when default=max25e0 +# F10 → 6 (CONNECT) then SEND … or F10 → 4 +``` + +## Connection matrix + +| Mode | Target | +|------|--------| +| Unix socket | `/run/max25/modem.sock` | +| TCP | `127.0.0.1:7325` or remote host | +| Flags | `--ax25-ui` (default on) · `--no-ax25-ui` for plain SEND | + +```bash +max25-terminal -U /run/max25/modem.sock +max25-terminal -T -H 127.0.0.1 -p 7325 +# optional override after connect: +max25-terminal -U /run/max25/modem.sock -d max25e0 +``` + +## Device selection + +| Method | When | +|--------|------| +| max25d `[devices] default = …` | Session starts on that id — **no** `-d` needed | +| `-d` / `--device ID` | CLI `SET DEVICE` right after connect | +| Type `SET DEVICE <id>` | In the terminal prompt | +| F10 → **7** | Menu: Change DEVICE (TX target) | + +`CONNECT` (F10 → **6**, or type `CONNECT`) attaches the **currently selected** device. + +## Command matrix + +| Command | Action | +|---------|--------| +| `SET DEVICE <id>` | Select RF backend | +| `GET DEVICES` | List enabled devices | +| `CONNECT` | Attach selected device | +| `SEND …` | Transmit payload | +| F10 menu | Device ops, status, bans | + +## F10 menu + +| Key | Action | +|-----|--------| +| 1 | CALLERID | +| 2 | CALLID | +| 3 | Status | +| 4 | Send line | +| 5 | RX only (Monitor) | +| 6 | Connection on/off (`CONNECT` / `DISCONNECT`) | +| 7 | Change DEVICE | +| 8 | List devices (`GET DEVICES`) | +| 0 | Quit | + +## Identity matrix + +| Terminal field | AX.25 field | +|----------------|-------------| +| CALLERID | source address | +| CALLID | destination address | + +## Related + +| Goal | Doc | +|------|-----| +| M25/1 protocol | [MAX25-CLIENT.md](MAX25-CLIENT.md) | +| Operator runbook | [MAX25-OPERATOR-RUNBOOK.md](MAX25-OPERATOR-RUNBOOK.md) | +| BayCom/based (bcpr) | [BAYCOM.md](BAYCOM.md) | +| TX/RX release test | [TX-RX-TEST.md](TX-RX-TEST.md) | diff --git a/docs/MERGE-REPORT.md b/docs/MERGE-REPORT.md new file mode 100644 index 0000000..32ca145 --- /dev/null +++ b/docs/MERGE-REPORT.md @@ -0,0 +1,36 @@ +# Merge report · MAX25-Stack 1.8.0 + +Archive of stack merge history — BayCom, CRDOP, TNC tools into unified MAX25-Stack. + +## Merge source matrix + +| Source stack | Target path | Status | +|--------------|-------------|--------| +| BayCom PR-Stack | `stacks/baycom-pr/` | merged | +| CRDOP dev track | `stacks/crdop/` | merged | +| TNC tools | `stacks/tncs/` | merged | +| Terminal | `stacks/terminal/` | merged | +| Daemon | `stacks/daemon/` | merged | + +## Version matrix + +| Component | Version note | +|-----------|--------------| +| MAX25-Stack | 1.8.0 (product) | +| BayCom PR-Stack upstream | 1.0.0 | +| CRDOP dev track | CUR999 until standalone milestone | + +## Policy matrix + +| Rule | Detail | +|------|--------| +| Single repo | all stacks under MAX25-Stack | +| HyBBX | external consumer — `share/hybbx/` fragments | +| Docs | English, matrix index in `docs/README.md` | + +## Related + +| Goal | Doc | +|------|-----| +| Architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | +| Paths | [PATHS.md](PATHS.md) | diff --git a/docs/MODULAR-TCPIP-SERVER.md b/docs/MODULAR-TCPIP-SERVER.md new file mode 100644 index 0000000..5e38266 --- /dev/null +++ b/docs/MODULAR-TCPIP-SERVER.md @@ -0,0 +1,33 @@ +# Modular TCP/IP server · MAX25-Stack 1.8.0 + +Main + Secondary TCP/IP topology service — DEV-Level 1. + +## Topology matrix + +| Role | Function | +|------|----------| +| Main | TCP/IP hub, coordinates secondaries | +| Secondary | RF backend + registers with Main | +| Cross-host | LAN `host:port` peers | + +## Component matrix + +| Item | Path | +|------|------| +| Service | `modular_tcp_server.py` | +| INI Main | `share/max25/max25d.main.ini.example` | +| INI Secondary | `share/max25/max25d.secondary-linux.ini.example` | + +## Platform matrix + +| Host | Role | +|------|------| +| FreeBSD | TCP/IP hub + CRDOP (documented split) | +| Linux | TNC / BayCom Secondary | + +## Related + +| Goal | Doc | +|------|-----| +| Architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | +| FreeBSD | [FREEBSD-AX25.md](FREEBSD-AX25.md) | diff --git a/docs/NETDEV.md b/docs/NETDEV.md new file mode 100644 index 0000000..b4ded39 --- /dev/null +++ b/docs/NETDEV.md @@ -0,0 +1,27 @@ +# Virtual netdev max25d0 · MAX25-Stack 1.8.0 + +TUN interface plan for modular TCP/IP — DEV-Level 1/2. + +## Interface matrix + +| Item | Value | +|------|-------| +| TUN name | `max25d0` (Linux) | +| Purpose | IPv4/IPv6 over AX.25 path | +| Status | planned / scaffold | +| Sidecar | `max25-tun` (DEV-Level 2) | + +## Relation matrix + +| Component | Role | +|-----------|------| +| max25d | KISS/device backends | +| max25d0 | IP encapsulation endpoint | +| modular TCP/IP server | Main/Secondary split | + +## Related + +| Goal | Doc | +|------|-----| +| Modular TCP/IP | [MODULAR-TCPIP-SERVER.md](MODULAR-TCPIP-SERVER.md) | +| v2 scope | [V2.0.0-SCOPE.md](V2.0.0-SCOPE.md) | diff --git a/docs/PACKET-RADIO.md b/docs/PACKET-RADIO.md new file mode 100644 index 0000000..5876ff3 --- /dev/null +++ b/docs/PACKET-RADIO.md @@ -0,0 +1,46 @@ +# Packet Radio & AX.25 · MAX25-Stack 1.8.0 + +Technical reference for on-air and host-side AX.25/KISS behaviour in MAX25. + +## Layer matrix + +| Layer | MAX25 owns | +|-------|------------| +| Operator UI | `max25-terminal` | +| Session / IPC | `max25d` M25/1 | +| Device prep | boot-wait, modprobe, KISS PTY | +| AX.25 codec | `ax25_codec.py` / `kiss_bridge.py` | +| KISS framing | FEND/FESC, port nibble | +| HyBBX attach | external — after stack up | + +## Address matrix + +| Rule | Value | +|------|-------| +| Call body | 1–6 chars A–Z/0–9 | +| SSID | `-0` … `-15` | +| Path order | DEST → DIGI* → SOURCE | + +## KISS matrix + +| Item | Rule | +|------|------| +| FCS on DATA to TNC | stripped — TNC adds on air | +| KISS return recovery | `0xC0 0xFF 0xC0` before prep | +| MYCALL | MAX25 prep — not HyBBX | + +## CRDOP note matrix + +| Item | Value | +|------|-------| +| Device id | `soft-crdop` | +| Speed | 1200 bd primary, up to 19200 bd | +| Duplex | half and full | +| TCP ports | 8515 control / 8516 data | + +## Related + +| Goal | Doc | +|------|-----| +| Device workflow | [PLUGINS-DEVICE-MODEL.md](PLUGINS-DEVICE-MODEL.md) | +| HyBBX | [HYBBX.md](HYBBX.md) | diff --git a/docs/PATHS.md b/docs/PATHS.md new file mode 100644 index 0000000..c0ba5d3 --- /dev/null +++ b/docs/PATHS.md @@ -0,0 +1,46 @@ +# Repository paths · MAX25-Stack + +Canonical directory map for contributors and operators. + +## Top-level matrix + +| Path | Role | +|------|------| +| `stacks/daemon/` | max25d supervisor (`max25d` / `max25d.py`) — **not** the terminal | +| `stacks/terminal/` | operator client (`max25-terminal`) | +| `stacks/tncs/` | TNC boot-wait, recovery | +| `stacks/max25-bcpr/` | BayCom/based SER12 (max25-bcpr) · `max25-bcprd` / `max25-bcpr-ctl` | +| `stacks/crdop/` | MAX25-SoftModem | +| `plugins/` | hardware/device registry | +| `share/max25/` | max25d INI examples | +| `share/hybbx/` | HyBBX attach fragments | +| `docs/` | shipped documentation | +| `scripts/` | build, test, install · `tx-rx-test.sh` | + +## Operator binaries (do not invent paths) + +| Binary | Canonical | +|--------|-----------| +| max25d | `stacks/daemon/max25d` · install `/usr/local/bin/max25d` | +| max25-terminal | **`scripts/run-max25-terminal.sh`** · `/usr/local/bin/max25-terminal` · `build*/bin/max25-terminal` | +| max25-bcpr-ctl | `stacks/max25-bcpr/tools/max25-bcpr-ctl` · install `/usr/local/sbin/max25-bcpr-ctl` | +| max25-bcprd | `build*/bin/max25-bcprd` · install `/usr/local/bin/max25-bcprd` | +| max25d (start) | **`scripts/run-max25d.sh`** · `stacks/daemon/max25d` | + +Wrong: `stacks/daemon/max25-terminal` (does not exist). +Wrong: relying on leftover ELF `stacks/terminal/max25-terminal` (gitignored; often stale, missing `-d`). + +## Config matrix + +| Live config | Path | +|-------------|------| +| Operator secrets | `./local/` (gitignored) | +| System INI example | `share/max25/max25d.ini.example` | +| HyBBX fragments | `share/hybbx/*-host.ini.example` | + +## Related + +| Goal | Doc | +|------|-----| +| Development | [DEVELOPMENT.md](DEVELOPMENT.md) | +| Doc index | [README.md](README.md) | diff --git a/docs/PLATFORMS.md b/docs/PLATFORMS.md new file mode 100644 index 0000000..12f3c3a --- /dev/null +++ b/docs/PLATFORMS.md @@ -0,0 +1,34 @@ +# Platforms · MAX25-Stack 1.8.0 + +Supported and planned platforms for max25d and max25-terminal. + +## Component matrix + +| Component | Linux | FreeBSD | Other | +|-----------|-------|---------|-------| +| `max25d` (full RF) | yes | scaffold | planned | +| `max25-terminal` | yes | yes | AmigaOS, macOS, Windows | +| CRDOP | ALSA | OSS | — | +| BayCom kernel | yes | no | — | + +## Priority matrix + +| Priority | Platform | +|----------|----------| +| 1 | Linux/KLinux (full) | +| 2 | FreeBSD server + CRDOP | +| 3 | OpenBSD → NetBSD → macOS → Windows | + +## Interface name matrix + +| Item | Linux name | +|------|------------| +| TUN (when shipped) | `max25d0` | +| BayCom netdev | `bcsf0` | + +## Related + +| Goal | Doc | +|------|-----| +| FreeBSD plan | [FREEBSD-AX25.md](FREEBSD-AX25.md) | +| v2 scope | [V2.0.0-SCOPE.md](V2.0.0-SCOPE.md) | diff --git a/docs/PLUGINS-DEVICE-MODEL.md b/docs/PLUGINS-DEVICE-MODEL.md new file mode 100644 index 0000000..266cbf7 --- /dev/null +++ b/docs/PLUGINS-DEVICE-MODEL.md @@ -0,0 +1,36 @@ +# Plugins & device model · MAX25-Stack 1.8.0 + +Unified five-step device workflow for all RF backends. + +## Workflow matrix + +| Step | Action | +|------|--------| +| 1 | Select operating mode (`standalone`, `hybbx-host`, `service`) | +| 2 | Select hardware class (`tncs`, `modems`, `soft-modems`) | +| 3 | Select device id from registry | +| 4 | Run prep (`max25-ctl start …`) | +| 5 | Verify M25/1 + optional HyBBX attach | + +## Registry matrix + +| Layer | Source | +|-------|--------| +| Manifest | `plugins/manifest.yaml` | +| Discovery | `./scripts/discover-plugins.sh` | +| HyBBX mode | `plugins/betriebsform/hybbx-host/` | + +## Device class matrix + +| Hardware | Devices | Protocol | +|----------|---------|----------| +| `tncs` | `tnc2c`, (deferred `pktnc2`) | KISS serial | +| `modems` | `max25e0` / `baycom-kiss` | bcpr SER12 / USB KISS | +| `soft-modems` | `soft-crdop` | M25 host TCP + ALSA | + +## Related + +| Goal | Doc | +|------|-----| +| Full device list | [DEVICES-LIST-FULL.md](DEVICES-LIST-FULL.md) | +| Architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..6f5b79f --- /dev/null +++ b/docs/README.md @@ -0,0 +1,40 @@ +# Documentation index · MAX25-Stack 1.8.0 + +Compact doc map for MAX25 — start at MASTER-GUIDE for linear operator flow. + +## By role matrix + +| Role | Document | +|------|----------| +| Master operator guide | [MASTER-GUIDE.md](MASTER-GUIDE.md) | +| TNC / modem bring-up | [DEV/TNC-MODEM-DEV.md](DEV/TNC-MODEM-DEV.md) | +| Host setup | [LINUX-HOST-SETUP.md](LINUX-HOST-SETUP.md) | +| Device workflow | [PLUGINS-DEVICE-MODEL.md](PLUGINS-DEVICE-MODEL.md) | +| Terminal operator | [MAX25-TERMINAL.md](MAX25-TERMINAL.md) | +| Client / M25/1 | [MAX25-CLIENT.md](MAX25-CLIENT.md) | +| HyBBX integrator | [HYBBX.md](HYBBX.md) | +| BayCom / PC-COM | [BAYCOM.md](BAYCOM.md) | +| BayCom freeze warning (RX/TX) | [BAYCOM-FREEZES.md](BAYCOM-FREEZES.md) | +| TX/RX release test (TNC + BayCom/based) | [TX-RX-TEST.md](TX-RX-TEST.md) | +| Operator runbook | [MAX25-OPERATOR-RUNBOOK.md](MAX25-OPERATOR-RUNBOOK.md) | +| Contributor | [DEVELOPMENT.md](DEVELOPMENT.md) | + +## Technical reference matrix + +| Topic | Document | +|-------|----------| +| Architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | +| Packet radio / AX.25 | [PACKET-RADIO.md](PACKET-RADIO.md) | +| CRDOP / SoftModem | [CRDOP.md](CRDOP.md) | +| Platforms | [PLATFORMS.md](PLATFORMS.md) | +| FreeBSD port | [FREEBSD-AX25.md](FREEBSD-AX25.md) | +| Modular TCP/IP | [MODULAR-TCPIP-SERVER.md](MODULAR-TCPIP-SERVER.md) | +| v1 scope | [V1.0.0-SCOPE.md](V1.0.0-SCOPE.md) | +| v2 goals | [V2.0.0-SCOPE.md](V2.0.0-SCOPE.md) | + +## Related + +| Goal | Doc | +|------|-----| +| Root README | [../README.md](../README.md) | +| Release gates | [../RELEASE-READINESS.md](../RELEASE-READINESS.md) | diff --git a/docs/TX-RX-TEST.md b/docs/TX-RX-TEST.md new file mode 100644 index 0000000..404323e --- /dev/null +++ b/docs/TX-RX-TEST.md @@ -0,0 +1,137 @@ +# TX / RX release test · MAX25-Stack + +**RX before TX (§0.20):** live `--tx` requires Soft-DCD/noise (`dcd-bc*` / `rx-activity-bc*`) or TNC RX CONNECT in the same run. Override only `--force-tx` (against policy). +**Root (§0.21):** start via `scripts/run-max25d.sh` (auto sudo/su). + + +Unified operator and CI test for **TX** and **RX** on both device classes: + +| Class | Public mark | Internal / code | +|-------|-------------|-----------------| +| Modem (SER12 / PC-COM) | **BayCom/based** | **bcpr** | +| Classic TNC | TNC / KISS serial | `tnc2c`, `pktnc2`, … | + +Entry: `scripts/tx-rx-test.sh`. Offline **L0** ships in release gates (`ctest`, `max25_test`, `release-check.sh`). Live / TX levels are **manual** (operator-gated). + +## Levels + +| Level | Name | Default | Scope | +|-------|------|---------|-------| +| **L0** | Offline | **always** | Host CONNECT/SEND loopback · KISS encode/decode · TNC recovery units · bcpr HDLC/dry-run smoke | +| **L1** | Soft preflight | `--level 1` | bcpr preflight soft · TNC profile present | +| **L2/L3** | Live RX | `--live` | Modem: timed `max25-bcprd` attach + listen (nofreeze). TNC: unix `CONNECT` + STATUS | +| **L4** | Capped TX | `--live --tx` | Modem: ~3s KISS UI (default `--tx-seconds 3`, ≈376B info) + MCR proof. TNC: one `SEND` on live socket | + +Defaults: **NO TX**. Live seconds capped (default 15, max 60). No calibrate. No kernel `baycom_ser_fdx`. + +L4 modem notes: + +| Item | Contract | +|------|----------| +| Payload | Default ~3s PTT (proven AX25WRK1 inject: info **376B** → ~3005 ms MCR) — not a 23-byte stub | +| `--tx-seconds N` | Target key window (1–12); longer than ~3s uses multiple bursts (`BCPR_MAXFLEN` cap) | +| Host proof | Script requires UART **MCR** key (`0x0e`/`0x0f`); `PASS:` without MCR = fail | +| Live stack | Reuses running `max25-bcprd` + `kiss_link` when present (no second attach / no blanket `pkill`) | +| KISS peer | Smoke keeps the KISS slave open during TX (standalone attach); closing after write → POLLHUP → no MCR | +| RF evidence | Wattmeter needle + radio TX/PTT LED during the key window — not automated | + +## Operator RF evidence (optional · not automated) + +On a live host with radio + in-line wattmeter (e.g. AX25WRK1), during `--live --tx` (~3s default): + +| Check | Pass | +|-------|------| +| External power meter | Needle deflection during TX burst | +| Radio TX / PTT LED | Lit for the TX window (~3s) | +| Script line | `MCR_keyed=…ms` and `PASS: L4 TX MCR keyed` | + +Host write-only `PASS:` without MCR is insufficient. SQ closed / no speaker audio does **not** disprove TX. Not in CI. + +## Offline (CI / release) + +```bash +cd /path/to/MAX25-Stack + +# Operator entry (L0) +./scripts/tx-rx-test.sh + +# Or via CMake +cmake -B build -DCMAKE_BUILD_TYPE=Release -DMAX25_BUNDLE_AX25=OFF -DMAX25_BUILD_MAX25_BCPR=ON +cmake --build build -j"$(nproc)" +cmake --build build --target max25_tx_rx_test +# also: ctest -R max25_tx_rx_offline --output-on-failure +# umbrella: cmake --build build --target max25_test +# release: bash scripts/release-check.sh +``` + +Pass criterion: all `PASS:` / `OK:` lines; exit 0. + +## Live — BayCom/based (bcpr / PC-COM) + +Requires root + live INI (`dry_run=no`, real IRQ/serial). Prefer dedicated host. See [BAYCOM.md](BAYCOM.md) · [BAYCOM-FREEZES.md](BAYCOM-FREEZES.md). + +```bash +# Soft L1 + short live RX (radio may be OFF) +sudo ./scripts/tx-rx-test.sh --device modem --live --seconds 15 \ + -c /etc/max25/max25-bcpr.ini + +# Capped TX (~3s PTT — watch wattmeter / TX LED; MCR required for PASS) +sudo ./scripts/tx-rx-test.sh --device modem --live --tx --tx-seconds 3 \ + -c /etc/max25/max25-bcpr.ini + +# Longer attach window (optional) +sudo ./scripts/tx-rx-test.sh --device modem --live --tx --seconds 20 --tx-seconds 3 \ + -c /etc/max25/max25-bcpr.ini +``` + +Equivalent max25-bcpr-only path: `stacks/max25-bcpr/tools/max25-bcpr-ctl smoke [--live] [--tx] [--tx-seconds N]`. + +Prefer a running max25d/max25-bcprd stack (script reuses `kiss_link`). Fresh timed `max25-bcprd` only when none is running. + +max25d path (after stack up): `max25-terminal -U /run/max25/modem.sock` (with `default = max25e0`, no `-d` required) → `CONNECT` → `SEND …` — host TX keys UART MCR on SER12. Prefer PATH/`build*/bin` (stale `stacks/terminal/max25-terminal` may lack `-d`). For ~3s visible PTT use KISS inject ≥~376B info (unix `SEND` is capped by max25d `MAX_PAYLOAD=256` ≈2.2s). + +## Live — classic TNC + +Start **max25d** with a TNC device (`tnc2c` / `pktnc2`) so `/run/max25/modem.sock` (or `/tmp/max25/modem.sock`) exists. + +```bash +# RX readiness (CONNECT + STATUS) — no SEND +./scripts/tx-rx-test.sh --device tnc --live + +# One capped SEND (keys radio if PTT wired) +./scripts/tx-rx-test.sh --device tnc --live --tx +``` + +Override socket: `MAX25_SOCK=/run/max25/modem.sock`. + +## Both classes + +```bash +./scripts/tx-rx-test.sh --device all # L0 offline +sudo ./scripts/tx-rx-test.sh --device all --live -c /etc/max25/max25-bcpr.ini +``` + +TNC live still needs a running max25d socket; modem live needs bcpr INI. + +## What is in release / CI + +| Gate | Runs | +|------|------| +| `scripts/tx-rx-test.sh` (L0) | Offline TX/RX for TNC + bcpr | +| CTest `max25_tx_rx_offline` | Same | +| Target `max25_tx_rx_test` | Same | +| `max25_test` | Depends on `max25_tx_rx_test` | +| `scripts/release-check.sh` | Invokes L0 tx-rx-test | +| GitHub CI | `max25_test` + `release-check.sh` | + +**Not** in CI: `--live` / `--tx` (hardware / RF). + +## Related + +| Doc | Role | +|-----|------| +| [BAYCOM.md](BAYCOM.md) | BayCom/based bring-up | +| [BAYCOM-FREEZES.md](BAYCOM-FREEZES.md) | Freeze warning | +| [HARDWARE-ACCEPTANCE.md](HARDWARE-ACCEPTANCE.md) | Manual RF matrix | +| [`stacks/max25-bcpr/README.md`](../stacks/max25-bcpr/README.md) | bcpr smoke L0–L4 | +| [`stacks/tncs/docs/TNC-RECOVERY.md`](../stacks/tncs/docs/TNC-RECOVERY.md) | TNC recovery | diff --git a/docs/V1.0.0-SCOPE.md b/docs/V1.0.0-SCOPE.md new file mode 100644 index 0000000..33629dc --- /dev/null +++ b/docs/V1.0.0-SCOPE.md @@ -0,0 +1,42 @@ +# v1.0.0 scope · MAX25-Stack 1.8.0 + +Baseline release scope — still authoritative for v1 device set. + +## Active device matrix + +| Device | Status | HyBBX | +|--------|--------|-------| +| `tnc2c` | active | `packet_radio` | +| `max25e0` | active | `bcpr` (kernel baycom-ser12 removed) | +| `soft-crdop` | active | `crdop` | + +## Goal matrix + +| # | Goal | +|---|------| +| 1 | Operator brings up one radio path without HyBBX | +| 2 | Clear HyBBX attach contract | +| 3 | Offline CI gates pass on Linux | + +## CRDOP matrix (v1) + +| Topic | Value | +|-------|-------| +| Build | ON by default | +| Speed | 1200 bd+, max 19200 bd | +| Phase | development and test | +| Audio | ALSA direct | + +## Deferred matrix + +| Item | Target | +|------|--------| +| `pktnc2`, `baycom-par96`, `baycom-kiss` | v1.1+ | +| Rootless daily BayCom | v2.0.0 | + +## Related + +| Goal | Doc | +|------|-----| +| v2 goals | [V2.0.0-SCOPE.md](V2.0.0-SCOPE.md) | +| Release readiness | [../RELEASE-READINESS.md](../RELEASE-READINESS.md) | diff --git a/docs/V2.0.0-SCOPE.md b/docs/V2.0.0-SCOPE.md new file mode 100644 index 0000000..3e6873c --- /dev/null +++ b/docs/V2.0.0-SCOPE.md @@ -0,0 +1,35 @@ +# v2.0.0 scope · MAX25-Stack 1.8.0 + +Planning document — mandatory v2 goals for home Linux operation. + +## DEV-Level matrix + +| Level | Focus | Status | +|-------|-------|--------| +| DEV-Level 1 | Modular TCP/IP, Linux+FreeBSD, `max25d0`, rootless foundation | active | +| DEV-Level 2 | Main+Secondary supervision, `max25-tun` | planned | +| DEV-Level 3 | WebSocket gateway | planned | +| DEV-Level 4 | CRDOP expansion | deferred | +| Later | AI/assistant — deferred | deferred | + +## Mandatory goal matrix + +| Goal | Detail | +|------|--------| +| Rootless daily operation | no sudo for routine max25d (v2 target) | +| One-command setup | guided install for home Linux | +| Cross-platform base | Linux + FreeBSD before mid-tier features | + +## CRDOP policy matrix + +| Phase | CRDOP scope | +|-------|-------------| +| v1 / DEV-Level 1 | minimal/native — build + backend + bench | +| DEV-Level 4 | OSS polish, G3RUH, deeper integration | + +## Related + +| Goal | Doc | +|------|-----| +| Modular TCP/IP | [MODULAR-TCPIP-SERVER.md](MODULAR-TCPIP-SERVER.md) | +| Platforms | [PLATFORMS.md](PLATFORMS.md) | diff --git a/docs/WEBSOCKET.md b/docs/WEBSOCKET.md new file mode 100644 index 0000000..1077637 --- /dev/null +++ b/docs/WEBSOCKET.md @@ -0,0 +1,129 @@ +# WebSocket browser terminal · MAX25-Stack + +Remote operator terminal over WebSocket — same M25/1 session model as `max25-terminal`, via loopback proxy. + +## Architecture + +``` +Browser (PHP + JS) + → httpd reverse-proxy WS /max25-websocket/ws (TLS/wss at edge) + → max25-ws-proxy 127.0.0.1:7326/max25 + → max25d M25/1 TCP 127.0.0.1:7325 +``` + +WebSocket is **not** inside max25d (unlike hyBBX in-process WebSocket). The proxy forwards bytes without protocol translation. + +| Component | Path | +|-----------|------| +| Browser UI | `stacks/web/share/reverse-proxy/docroot/max25-websocket/` | +| Session defaults | `/etc/max25/web-terminal.ini` (see `web-terminal.ini.example`) | +| WebSocket proxy | `max25-ws-proxy` — config `web-proxy.ini` | +| Primary CLI client | `max25-terminal` (unchanged) | + +## Ports + +| Port | Service | +|------|---------| +| **7325** | max25d M25/1 TCP | +| **7326** | WebSocket proxy (loopback; expose via httpd only) | + +## Session defaults (`web-terminal.ini`) + +Copy `share/web-terminal.ini.example` to `/etc/max25/web-terminal.ini` or set `MAX25_WEB_TERMINAL_INI`. + +Values mirror max25d `[modem]` and `[devices] default`. Applied **per WebSocket session** on connect: + +| Key | Source | Meaning | +|-----|--------|---------| +| `device` | `[session]` or max25d `[devices] default` | One device per session (`SET DEVICE`) | +| `callerid` | `[session]` or max25d `[modem]` | `SET CALLERID` if different from daemon | +| `callid` | `[session]` or max25d `[modem]` | `SET CALLID` if different | +| `ax25_ui` | `[session]` or max25d `[modem]` | `SET AX25_UI on\|off` | +| `connect_on_start` | `[session]` | `CONNECT` after setup (default yes) | + +Optional `max25d_ini` under `[max25-web-terminal]` merges missing keys from live max25d config. + +## Browser UI + +### Header + +Live fields: **DEVICE**, **CALLERID**, **CALLID**, **ax25-ui**, **connected**. + +**Device dropdown** lists only ids returned by `GET DEVICES` from max25d. Unknown ids are rejected. + +### Menu (F10 equivalent) + +Non-intrusive **Menu ▾** dropdown plus slash commands: + +| Command | Action | +|---------|--------| +| `/callerid [id]` | `SET CALLERID` | +| `/callid [id]` | `SET CALLID` | +| `/status` | `GET STATUS` | +| `/send <text>` | `SEND` | +| `/monitor [on\|off\|toggle]` | `MONITOR` | +| `/connect` / `/disconnect` | `CONNECT` / `DISCONNECT` | +| `/devices` | `GET DEVICES` (device overview) | +| `/device <id>` | `SET DEVICE` (max25d id only) | +| `/ax25_ui on\|off` | `SET AX25_UI` | +| `/help` | Command list | + +Plain text (no `/`) is sent as **`SEND`** — same as `max25-terminal` Enter. + +### Multiple sessions + +Each browser tab / WebSocket connection is an independent M25/1 client. Same `web-terminal.ini` defaults apply; per-session changes via `/` commands or dropdown. + +## Deploy + +```bash +cmake --install $BUILD --prefix $PREFIX +``` + +Installs: + +- `$PREFIX/bin/max25-ws-proxy` +- `$PREFIX/share/max25/web-proxy.ini.example` +- `$PREFIX/share/max25/web-terminal.ini.example` +- `$PREFIX/share/max25/reverse-proxy/` (httpd snippets + `docroot/`) + +### systemd (proxy) + +Example: `share/max25/max25-ws-proxy.service.example` — run proxy on loopback; point httpd `WS` to `127.0.0.1:7326/max25`. + +### httpd + +See `share/max25/reverse-proxy/{nginx,apache2,lighttpd}.conf.example` — proxy `WS /max25-websocket/ws` to the loopback WebSocket service. + +## Local dev + +```bash +./stacks/web/scripts/dev-server.sh +``` + +Open `http://127.0.0.1:8080/` — requires max25d on TCP 7325 and proxy on 7326. + +## max25-terminal device overview + +CLI client F10 menu: + +| # | Action | +|---|--------| +| 8 | List DEVICES (`GET DEVICES` → RX pane) | +| 7 | Change DEVICE (lists devices first, then prompt) | + +Device list at session start after `CONNECT`. + +## Security + +- Proxy binds **loopback** by default — expose only through httpd + TLS. +- Optional `tcp_password` in `web-proxy.ini` `[upstream]` when max25d `[network] tcp_password` is set. +- No browser-side auth beyond site/httpd policy. + +## Related + +| Doc | Topic | +|-----|-------| +| [MAX25-TERMINAL.md](MAX25-TERMINAL.md) | CLI operator client | +| [MAX25-CLIENT.md](MAX25-CLIENT.md) | M25/1 protocol | +| [stacks/web/README.md](../stacks/web/README.md) | Stack build / smoke | |
