diff --git a/docs/micromate_protocol_reference.md b/docs/micromate_protocol_reference.md index 6350d69..1e82239 100644 --- a/docs/micromate_protocol_reference.md +++ b/docs/micromate_protocol_reference.md @@ -449,6 +449,11 @@ memory 15,000,000 total and free (no events stored). Series III has one config and nothing to enumerate. 15. **`SUB 0x1C` carries the device clock** (day/month/year/h/m/s at `data[13:21]`). Nothing else read so far reports the unit's own time. +16. **There is a generic file transfer addressed by full path** — `0x94`/`0x48` + read, `0x8D`/`0x8E` write. Series III has nothing comparable; its config is + reachable only through dedicated commands. +17. **The scheduler is a separate file**, `\system\schedule\schedule.dat`, + and a schedule entry names a **setup file** to load. --- @@ -649,10 +654,21 @@ The unit's help text describes selecting, renaming and deleting them, and the event list records which setup file produced each event. Filesystem primitives exist internally (`NS_ReadFile_internal`, -`NS_WriteFile_internal`, `NS_SeekFile_internal`), but **no generic -file-transfer command is exposed on the wire** — the only file-transfer string -is `CMD_STOP_CALLHOME_FILETRANSFER`. So setups are unlikely to be pushed as -raw `.MMB` blobs over the protocol. +`NS_WriteFile_internal`, `NS_SeekFile_internal`). + +> ⚠ **RETRACTED 2026-09-24.** This section originally concluded "**no generic +> file-transfer command is exposed on the wire**", reasoning from the absence of +> firmware strings. **That was wrong.** `SUB 0x94` / `0x48` / `0x8D` / `0x8E` +> are exactly that — a read/write file transfer addressed by **full filesystem +> path** — and they were caught in the open on the first capture that touched +> the scheduler. See *The scheduler, and a generic file transfer* below. +> +> The lesson is the usual one: absence of a firmware string is not absence of a +> command. The dispatch is a 68K jump table and the commands carry no strings +> of their own. +> +> The *setups* half of the original claim survives: setups are **not** pushed as +> raw `.MMB` blobs. They go through `0xDA` + the ordinary config block. ### `SUB 0x1A` reads the whole active setup — 2,092 bytes @@ -722,10 +738,14 @@ Data is exactly **256 bytes: the file name, null-padded, nothing else.** 54 45 53 54 31 2e 6d 6d 62 00 00 … "TEST1.mmb" + 247 × 0x00 ``` -This is the missing link in *setups are files*: there is no generic -file-transfer command because there does not need to be one. Thor names the -target file, then writes the ordinary config block into it. The unit acks with -`0x25` before any config bytes are sent. +This is the missing link in *setups are files*: Thor names the target file, then +writes the ordinary config block into it. The unit acks with `0x25` before any +config bytes are sent. + +Note `0xDA` takes a **bare filename** null-padded to 256 bytes. That is a +different mechanism from the path-addressed file transfer (`0x94` / `0x8D`, +which carry `\system\schedule\schedule.dat` unpadded) — setups do not go through +the file transfer, and the file transfer is not how setups are written. ### Reads are single-step — no probe @@ -920,6 +940,116 @@ a create and an overwrite. We have never seen this protocol report a *failed* write, so **do not treat a zero ack as proof a write was applied.** Read the config back and compare; `SUB 0x41` plus `SUB 0x1A` make that cheap. +## The scheduler, and a generic file transfer (2026-09-24) + +Capture: `bridges/captures/9-24-26 - micromate2/*_read_scheduler.bin`. +25 request frames, 25 responses, every checksum valid. + +Four operations in one capture, segmented by Thor's `POLL` preamble (marks are +not written into the raw `.bin` — in TCP mode seismo_lab logs them to the +on-screen log only): + +| frames | operation | +|---|---| +| 0–4 | read the schedule off the unit | +| 5–18 | push a setup — the sequence already documented above, unchanged | +| 19–21 | write the schedule back | +| 22–24 | enable the scheduler | + +### 🔑 `SUB 0x94` / `0x48` / `0x8D` / `0x8E` — file transfer by path + +**The unit will read and write files addressed by full filesystem path.** + +``` +0x94 → 0x6B open for READ +0x48 → 0xB7 read next page; repeat until an all-zero response +0x8D → 0x72 open for WRITE +0x8E → 0x71 write the file body +``` + +The path is plain ASCII, **unpadded**, with `offset` = its exact length: + +``` +5c 73 79 73 74 65 6d 5c 73 63 68 65 64 75 6c 65 5c 73 63 68 65 64 75 6c 65 2e 64 61 74 +\system\schedule\schedule.dat 29 bytes, offset = 0x001D +``` + +`0x94` and `0x8D` sent **byte-identical** 29-byte payloads — the same path, only +the command distinguishing read from write. + +The `0x48` read is paged, and the page number comes back in the response header +at `payload[3:5]`: + +| call | page | payload | content | +|---|---|---|---| +| 1st | `0x0000` | 15 B | descriptor — `04 00 … 01 00 00 00 00 00 01` | +| 2nd | `0x0002` | 535 B | the file body | +| 3rd | `0x0000` | 11 B | all zeros = **end of file** | + +⚠ This is the single most consequential find of the session, because it is not +specific to the scheduler. **`callhome.MMB` is a file too**, and the call-home +config is the last unsolved piece of the project. Reading it should be a +matter of pointing `0x94` at the right path. That is a *lead*, not a result — +no path other than `schedule.dat` has been tried. + +### The schedule file itself + +The write body is the read body minus an 11-byte response prefix (524 vs 535), +so both describe the same structure: + +``` +03 00 00 00 0f 03 02 [namelen] [setup-file name] …zeros… 27 03 10 +``` + +- **`[namelen]` is a length prefix**: `0x28` = 40 for the 40-character name read + off the unit, `0x09` = 9 for `TEST1.mmb` written back. Confirmed both ways. +- The trailing `27 03 10` sits at `0x108` in the write body and `0x113` in the + read — the same offset once the 11-byte prefix is accounted for. + +**A schedule entry names a setup file.** That is how the help text's "change +the record mode" works: an entry says *at this time, load this setup*. It also +means the scheduler and the setup list are coupled — deleting a setup that a +schedule references is a foot-gun worth checking before we ever expose either. + +⚠ **The entry internals are NOT decoded.** One entry, one capture, no +variation to diff against. `03 00 00 00 0f 03 02` and `27 03 10` are recorded +as observed bytes, nothing more. Decoding needs schedules that differ in a +known way — two entries, or one entry at a different time of day. + +### `SUB 0x47` — the scheduler enable, probably + +Step 4 is two bare `0x47` frames with no data, differing only in `params[7]`: + +``` +req params = 00 00 00 00 00 00 00 [01] 00 00 → rsp 04 00 … 00 [01] 00 00 00 00 00 01 +req params = 00 00 00 00 00 00 00 [03] 00 00 → rsp 04 00 … 00 [03] 00 00 00 00 00 01 +``` + +The response echoes the selector and ends `01`. Its 15-byte shape is identical +to the descriptor `0x48` returns on page 0. + +⚠ **Whether `0x47` sets or merely reads is genuinely undetermined.** Both calls +returned the same trailing `01`, and there is no before/after to compare — the +scheduler was enabled in this same capture, so no "disabled" reading exists. +`params[7]` is also the token position Series III uses, which is suggestive but +not evidence. **Do not implement an enable against this until a +disable-then-enable capture settles it.** + +### The scheduler enable is NOT in the setup config block + +A prediction made before this capture — that the `Scheduler On/Off` switch would +appear as a byte in the `0x71` block, because the unit's help text lists it in +the same edit screen as Record Mode and Sample Rate — **did not hold**. + +The `0x71`, `0x68` and `0x82` payloads are **byte-identical** to the previous +capture's, all three, zero differences. The scheduler was enabled without any +of them changing. + +⚠ The test is weaker than it looks: the operator re-sent the *same* config, so +a byte-identical block is also what "nothing changed" looks like. What it does +establish is that enabling the scheduler did **not** require a config write — +whatever `0x47` does, it does alone. + ## Monitoring control and the setup list (2026-09-24) Capture: `bridges/captures/9-24-26 - micromate2/*_turn_on_monitormode_*`.