Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ iPhone-style dark look (status bar, battery glyph, grouped settings cards).
enabling one frees the other.

### 🔭 Later
- **MeshCore companion bridge** — V0 protocol foundation is drafted, and an
initial `companion mc ...` USB serial-console smoke surface can report
snapshots and exercise send boundaries; the formal USB/BLE bridge remains
planned, and it is not official MeshCore app compatible unless the real
MeshCore app protocol is confirmed.
- **MeshCore companion bridge** — V0 USB foundation is in progress:
`companion mc ...` covers console smoke, and `companion mc usb on` enters
formal MC0 mode for identity/status/node/thread snapshots, send boundaries,
revision counters, and event controls. BLE transport remains planned, and it
is not official MeshCore app compatible unless the real MeshCore app protocol
is confirmed.
- **Roll the iPhone look everywhere** — grouped cards / dividers across Messages, Nodes, Contacts.
- **Local app platform** - scan local app manifests from `/sd/limitlezz/apps`,
`/sd/apps`, `/appfs/apps`, and simulator data dirs, then show accepted apps
Expand Down Expand Up @@ -185,7 +186,7 @@ iPhone-style dark look (status bar, battery glyph, grouped settings cards).
- [`docs/tdeck-firmware-audit.md`](docs/tdeck-firmware-audit.md) - current firmware audit and risk list.
- [`docs/tdeck-feature-inventory.md`](docs/tdeck-feature-inventory.md) - feature-by-feature implementation inventory.
- [`docs/tdeck-firmware-roadmap.md`](docs/tdeck-firmware-roadmap.md) - roadmap to a complete T-Deck firmware.
- [`docs/tdeck-meshcore-companion-protocol.md`](docs/tdeck-meshcore-companion-protocol.md) - draft Phase 5/V0.8 MeshCore companion line protocol.
- [`docs/tdeck-meshcore-companion-protocol.md`](docs/tdeck-meshcore-companion-protocol.md) - Phase 5/V0.8 MeshCore companion V0 protocol.
- [`docs/tdeck-hardware-dogfood-checklist.md`](docs/tdeck-hardware-dogfood-checklist.md) - stock-device hardware proof checklist.
- [`docs/tdeck-release-checklist.md`](docs/tdeck-release-checklist.md) - slow-host Actions artifact and COM8 release evidence checklist.
- [`docs/tdeck-troubleshooting.md`](docs/tdeck-troubleshooting.md) - build, flash, boot, radio, storage, Wi-Fi, and companion troubleshooting.
Expand Down
2 changes: 1 addition & 1 deletion docs/tdeck-feature-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Status labels:
| MeshCore self-advert TX | Partial, needs validation | Ed25519 identity, self-advert builder, serial/UI advert commands | Needs interop proof with real MeshCore nodes. |
| MeshCore public channel / rooms | Planned | README says receive/default Public channel still ahead | V0.6: implement group text decode/send, room model, and split airtime config. |
| MeshCore DMs | Planned | MeshCore contacts are non-messageable while gated | V0.7: implement key/session model, send path, ACKs, and UI routing. |
| MeshCore companion bridge | Planned/In progress | `docs/tdeck-meshcore-companion-protocol.md` drafts the V0 USB serial line protocol; `companion mc ...` provides an initial firmware smoke surface for snapshots, sends, and self-test | V0.8: formalize USB first, mirror to BLE later, and do not claim external MeshCore app compatibility until the real app protocol is confirmed. |
| MeshCore companion bridge | Partial/In progress | `docs/tdeck-meshcore-companion-protocol.md` defines the V0 USB serial line protocol; `companion mc ...` provides console smoke coverage, and `companion mc usb on` enters formal MC0 mode for identity/status/node/thread snapshots, send boundaries, event controls, revision counters, and bounded event drain | V0.8: broaden event/status coverage, mirror to BLE later, and do not claim external MeshCore app compatibility until the real app protocol is confirmed. |

## User Interface

Expand Down
19 changes: 12 additions & 7 deletions docs/tdeck-firmware-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ These maintainer-provided beta labels are the canonical near-term sequence. The
| V0.6 | MeshCore public chat and split airtime config | 🚧 Public chat send/receive hardware-verified; **split airtime may not be working — needs re-verification**; config UI still TODO |
| V0.6 | MeshCore public chat and split airtime config | In progress - public chat send/receive hardware-verified; split-airtime serial dwell/switch smoke passed on COM8; packet-loss, latency, and real dual-network traffic soak still open |
| V0.7 | MeshCore DMs and private chats | ✅ Encrypted DMs (X25519 ECDH + AES) send/receive hardware-verified against a real MeshCore peer |
| V0.8 | MeshCore USB companion and MeshCore BLE companion | 🚧 Protocol foundation drafted; USB/BLE implementation still planned and not external-app compatible yet |
| V0.8 | MeshCore USB companion and MeshCore BLE companion | In progress - USB MC0 mode now covers identity/status/node/thread snapshots, send boundaries, revision counters, event controls, and COM8 smoke hooks; BLE and external-app compatibility are still planned |
| V0.9 | Code review, optimization, and emoji polish | ⬜ Not started |
| V0.95 | Basic app SDK and infrastructure; Home UI supports adding apps and multiple home screens | 🚧 Local manifest scanner, Home paging, and detail shell started; runtime/catalog still TODO |
| V0.96 | Upgraded Wi-Fi password storage | ✅ Implemented on T-Deck hardware: credentials use ESP32 NVS, legacy `wifi.cfg` migrates/removes, and diagnostics do not print passwords |
Expand Down Expand Up @@ -189,17 +189,22 @@ Exit criteria:

Goal: expose MeshCore companion functionality only after native MeshCore messaging is stable.

**Status:** protocol foundation in progress with an initial USB serial-console
smoke surface. `companion mc hello|status|nodes|threads|send|dm|test` now
exercises the firmware-owned MeshCore snapshots and send boundaries for COM8
validation, while the formal `MC0` bridge, BLE transport, events, and real
external MeshCore app compatibility are still planned work.
**Status:** USB-first protocol foundation in progress. `companion mc
hello|status|nodes|threads|send|dm|test` still exercises the firmware-owned
MeshCore snapshots and send boundaries for COM8 validation, and formal
`companion mc usb on` MC0 mode now handles `HELLO`, `IDENTITY`, `STATUS`,
`NODES`, `THREADS`, `SEND_PUBLIC`, `SEND_DM`, `EVENTS`, and `EXIT` with
snapshot revisions plus a bounded event drain. BLE transport and real external
MeshCore app compatibility are still planned work.

Deliverables:

- Define the MeshCore companion protocol surface for node DB, public chat, private chats, and send/receive forwarding. Drafted as `docs/tdeck-meshcore-companion-protocol.md`.
- Add a USB serial-console smoke surface that reports MeshCore companion status, nodes, threads, Public send, DM send, and self-test.
- Implement MeshCore USB companion mode.
- Implement MeshCore USB companion mode. In progress: MC0 USB request/response
mode is implemented for identity, status, node/thread snapshots, send
boundaries, event controls, and reconnect/resync counters; deeper event
coverage and external protocol mapping remain.
- Implement MeshCore BLE companion mode.
- Add UI and serial commands that distinguish Meshtastic companion from MeshCore companion.
- Decide whether one companion session or one network can own the external-app bridge at a time.
Expand Down
35 changes: 21 additions & 14 deletions docs/tdeck-meshcore-companion-protocol.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# T-Deck MeshCore Companion V0 Protocol

Status: Phase 5 / V0.8 protocol foundation plus an initial firmware serial
smoke surface. The current firmware exposes `companion mc hello`, `status`,
`nodes`, `threads`, `send`, `dm`, and `test` for USB console validation; the
formal `MC0` request/response bridge, live events, BLE transport, and external
app compatibility are still planned.
Status: Phase 5 / V0.8 USB-first protocol foundation. The firmware exposes
`companion mc hello`, `status`, `nodes`, `threads`, `send`, `dm`, and `test`
for USB console validation, plus formal `companion mc usb on` MC0 mode for
`HELLO`, `IDENTITY`, `STATUS`, `NODES`, `THREADS`, `SEND_PUBLIC`, `SEND_DM`,
`EVENTS`, and `EXIT`. Snapshot revision counters and a bounded event drain are
implemented; BLE transport and external app compatibility are still planned.

## Goal

Expand Down Expand Up @@ -49,8 +50,12 @@ the normal console prompt. The firmware enters MC0 mode with:
```text
companion mc usb on
MC0 1 HELLO proto=0 app=limitlezz-smoke host=windows want=none
MC0 2 STATUS
MC0 3 NODES since=0 limit=5
MC0 2 IDENTITY
MC0 3 STATUS
MC0 4 NODES since=0 limit=5
MC0 5 THREADS since=0 limit=5
MC0 6 EVENTS mode=on types=nodes,messages,tx,status
MC0 7 EVENTS mode=off
MC0 99 EXIT
```

Expand Down Expand Up @@ -373,12 +378,14 @@ Rules:
2. Add an initial USB serial-console smoke surface for `hello`, `status`,
`nodes`, `threads`, Public send, DM send, and self-test.
3. Add a USB-only MeshCore companion mode with `HELLO`, `IDENTITY`, `STATUS`,
and `NODES`.
and `NODES`. Implemented.
4. Add `SEND_PUBLIC` and `SEND_DM` using the existing firmware-owned MeshCore
send paths.
send paths. Implemented.
5. Add event streaming for receive, send-status, node-change, and status
changes.
6. Add snapshot revision counters and reconnect/resync behavior.
changes. In progress: event controls and a bounded event drain are
implemented for node, message, and TX events.
6. Add snapshot revision counters and reconnect/resync behavior. Implemented
for node/thread snapshots and `STATUS`/`HELLO` resync.
7. Mirror the same logical protocol over BLE only after USB behavior is stable.
8. Revisit external-app compatibility only after the real MeshCore app protocol
is confirmed.
Expand All @@ -390,9 +397,9 @@ Rules:
`companion mc test`.
- Formal USB MC0 smoke is opt-in:
`python scripts/mc_companion_usb_smoke.py --mc0-usb` enters the configured
USB mode, sends `HELLO`, `STATUS`, and `NODES`, asserts `MC0 ... OK`,
`BEGIN`, and `END` response markers, then exits through the configured
`MC0 <id> EXIT` line.
USB mode, sends `HELLO`, `IDENTITY`, `STATUS`, `NODES`, `THREADS`, and
`EVENTS` on/off, asserts `MC0 ... OK`, revision, `BEGIN`, and `END`
response markers, then exits through the configured `MC0 <id> EXIT` line.
- If firmware lands different command names, use the smoke helper's
`--mc0-enter-command`, `--mc0-*-template`, `--mc0-*-marker`, and
`--mc0-exit-template` flags instead of editing firmware or weakening the
Expand Down
116 changes: 110 additions & 6 deletions scripts/mc_companion_usb_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,20 @@
DEFAULT_PUBLIC_TEMPLATE = "companion mc send {text}"
DEFAULT_MC0_ENTER_COMMAND = "companion mc usb on"
DEFAULT_MC0_HELLO_ID = "1"
DEFAULT_MC0_STATUS_ID = "2"
DEFAULT_MC0_NODES_ID = "3"
DEFAULT_MC0_IDENTITY_ID = "2"
DEFAULT_MC0_STATUS_ID = "3"
DEFAULT_MC0_NODES_ID = "4"
DEFAULT_MC0_THREADS_ID = "5"
DEFAULT_MC0_EVENTS_ON_ID = "6"
DEFAULT_MC0_EVENTS_OFF_ID = "7"
DEFAULT_MC0_EXIT_ID = "99"
DEFAULT_MC0_HELLO_TEMPLATE = "MC0 {id} HELLO proto=0 app=limitlezz-smoke host=windows want=none"
DEFAULT_MC0_IDENTITY_TEMPLATE = "MC0 {id} IDENTITY"
DEFAULT_MC0_STATUS_TEMPLATE = "MC0 {id} STATUS"
DEFAULT_MC0_NODES_TEMPLATE = "MC0 {id} NODES since=0 limit=5"
DEFAULT_MC0_THREADS_TEMPLATE = "MC0 {id} THREADS since=0 limit=5"
DEFAULT_MC0_EVENTS_ON_TEMPLATE = "MC0 {id} EVENTS mode=on types=nodes,messages,tx,status"
DEFAULT_MC0_EVENTS_OFF_TEMPLATE = "MC0 {id} EVENTS mode=off"
DEFAULT_MC0_EXIT_TEMPLATE = "MC0 {id} EXIT"
DEFAULT_STATUS_MARKERS = ["mccomp: status", "MeshCore", "MC companion"]
DEFAULT_TEST_MARKERS = ["PASS"]
Expand Down Expand Up @@ -180,27 +188,52 @@ def build_mc0_specs(args: argparse.Namespace) -> list[CommandSpec]:
hello_command = format_mc0_template(
"--mc0-hello-template", args.mc0_hello_template, args.mc0_hello_id
)
identity_command = format_mc0_template(
"--mc0-identity-template", args.mc0_identity_template, args.mc0_identity_id
)
status_command = format_mc0_template(
"--mc0-status-template", args.mc0_status_template, args.mc0_status_id
)
nodes_command = format_mc0_template(
"--mc0-nodes-template", args.mc0_nodes_template, args.mc0_nodes_id
)
threads_command = format_mc0_template(
"--mc0-threads-template", args.mc0_threads_template, args.mc0_threads_id
)
events_on_command = format_mc0_template(
"--mc0-events-on-template", args.mc0_events_on_template, args.mc0_events_on_id
)
events_off_command = format_mc0_template(
"--mc0-events-off-template", args.mc0_events_off_template, args.mc0_events_off_id
)
return [
CommandSpec(
"mc0 hello",
hello_command,
default_marker_override(
args.mc0_hello_marker,
[f"MC0 {args.mc0_hello_id} OK"],
[
f"MC0 {args.mc0_hello_id} OK",
"event_seq=",
"nodes_rev=",
"messages_rev=",
],
),
),
CommandSpec(
"mc0 identity",
identity_command,
default_marker_override(
args.mc0_identity_marker,
[f"MC0 {args.mc0_identity_id} OK", "addr=", "addr_format="],
),
),
CommandSpec(
"mc0 status",
status_command,
default_marker_override(
args.mc0_status_marker,
[f"MC0 {args.mc0_status_id} OK"],
[f"MC0 {args.mc0_status_id} OK", "event_seq=", "nodes_rev=", "messages_rev="],
),
),
CommandSpec(
Expand All @@ -211,6 +244,30 @@ def build_mc0_specs(args: argparse.Namespace) -> list[CommandSpec]:
[f"MC0 {args.mc0_nodes_id} BEGIN", f"MC0 {args.mc0_nodes_id} END"],
),
),
CommandSpec(
"mc0 threads",
threads_command,
default_marker_override(
args.mc0_threads_marker,
[f"MC0 {args.mc0_threads_id} BEGIN", f"MC0 {args.mc0_threads_id} END"],
),
),
CommandSpec(
"mc0 events on",
events_on_command,
default_marker_override(
args.mc0_events_on_marker,
[f"MC0 {args.mc0_events_on_id} OK", "events=on", "types="],
),
),
CommandSpec(
"mc0 events off",
events_off_command,
default_marker_override(
args.mc0_events_off_marker,
[f"MC0 {args.mc0_events_off_id} OK", "events=off"],
),
),
]


Expand Down Expand Up @@ -549,14 +606,23 @@ def main() -> int:
help="Seconds of quiet serial input that ends an optional MC0 read.",
)
mc0.add_argument("--mc0-hello-id", default=DEFAULT_MC0_HELLO_ID)
mc0.add_argument("--mc0-identity-id", default=DEFAULT_MC0_IDENTITY_ID)
mc0.add_argument("--mc0-status-id", default=DEFAULT_MC0_STATUS_ID)
mc0.add_argument("--mc0-nodes-id", default=DEFAULT_MC0_NODES_ID)
mc0.add_argument("--mc0-threads-id", default=DEFAULT_MC0_THREADS_ID)
mc0.add_argument("--mc0-events-on-id", default=DEFAULT_MC0_EVENTS_ON_ID)
mc0.add_argument("--mc0-events-off-id", default=DEFAULT_MC0_EVENTS_OFF_ID)
mc0.add_argument("--mc0-exit-id", default=DEFAULT_MC0_EXIT_ID)
mc0.add_argument(
"--mc0-hello-template",
default=DEFAULT_MC0_HELLO_TEMPLATE,
help="MC0 HELLO line template; supports {id}.",
)
mc0.add_argument(
"--mc0-identity-template",
default=DEFAULT_MC0_IDENTITY_TEMPLATE,
help="MC0 IDENTITY line template; supports {id}.",
)
mc0.add_argument(
"--mc0-status-template",
default=DEFAULT_MC0_STATUS_TEMPLATE,
Expand All @@ -567,15 +633,35 @@ def main() -> int:
default=DEFAULT_MC0_NODES_TEMPLATE,
help="MC0 NODES line template; supports {id}.",
)
mc0.add_argument(
"--mc0-threads-template",
default=DEFAULT_MC0_THREADS_TEMPLATE,
help="MC0 THREADS line template; supports {id}.",
)
mc0.add_argument(
"--mc0-events-on-template",
default=DEFAULT_MC0_EVENTS_ON_TEMPLATE,
help="MC0 EVENTS-on line template; supports {id}.",
)
mc0.add_argument(
"--mc0-events-off-template",
default=DEFAULT_MC0_EVENTS_OFF_TEMPLATE,
help="MC0 EVENTS-off line template; supports {id}.",
)
mc0.add_argument(
"--mc0-hello-marker",
action="append",
help="Override HELLO expected marker(s). Defaults to 'MC0 <hello-id> OK'.",
help="Override HELLO expected marker(s). Defaults to OK plus revision fields.",
)
mc0.add_argument(
"--mc0-identity-marker",
action="append",
help="Override IDENTITY expected marker(s). Defaults to OK plus identity fields.",
)
mc0.add_argument(
"--mc0-status-marker",
action="append",
help="Override STATUS expected marker(s). Defaults to 'MC0 <status-id> OK'.",
help="Override STATUS expected marker(s). Defaults to OK plus revision fields.",
)
mc0.add_argument(
"--mc0-nodes-marker",
Expand All @@ -585,6 +671,24 @@ def main() -> int:
"'MC0 <nodes-id> BEGIN' and 'MC0 <nodes-id> END'."
),
)
mc0.add_argument(
"--mc0-threads-marker",
action="append",
help=(
"Override THREADS expected marker(s). Defaults to both "
"'MC0 <threads-id> BEGIN' and 'MC0 <threads-id> END'."
),
)
mc0.add_argument(
"--mc0-events-on-marker",
action="append",
help="Override EVENTS-on expected marker(s). Defaults to OK plus events=on.",
)
mc0.add_argument(
"--mc0-events-off-marker",
action="append",
help="Override EVENTS-off expected marker(s). Defaults to OK plus events=off.",
)
mc0.add_argument(
"--mc0-exit-template",
default=DEFAULT_MC0_EXIT_TEMPLATE,
Expand Down
5 changes: 5 additions & 0 deletions scripts/serial_harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
import sys
import time

if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="backslashreplace")
if hasattr(sys.stderr, "reconfigure"):
sys.stderr.reconfigure(encoding="utf-8", errors="backslashreplace")

try:
import serial
from serial.tools import list_ports
Expand Down
12 changes: 6 additions & 6 deletions scripts/tdeck_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,16 @@ def nostub_upload(project_dir: Path, env_name: str, port: str, baud: int, artifa
"--baud",
str(baud),
"--before",
"default-reset",
"default_reset",
"--after",
"hard-reset",
"hard_reset",
"--no-stub",
"write-flash",
"--flash-mode",
"write_flash",
"--flash_mode",
"dio",
"--flash-freq",
"--flash_freq",
"80m",
"--flash-size",
"--flash_size",
"16MB",
"0x0",
str(bootloader),
Expand Down
Loading