# Native CANdi routing and Android DTC results — 2026-09-08 Original Tech2 and CANdi firmware ran locally in the Rust emulator on a Pixel 7, using direct VCX Nano USB to an owner-operated Saab 9-3. The original firmware produced the diagnostic requests, consumed real ECU responses and drew its own DTC read and clear screens. This path uses no Windows host or OEM J2534 DLL. [Article and actual Android screenshots](https://relevant-diann-djfremen2-c013cdc3.koyeb.app/static/android-native-dtc-2026-09-08.html). These are configuration-specific observations. They do not establish universal Nano, Chipsoft, MDI or vehicle compatibility. Existing catalog entries retain their own capture context; do not apply a CAN-ID alias without its bus and session. ## CANdi channel mapping | Native channel | Emulated controller | Register window | IRQ / vector | Bus in this profile | Nano channel | |---|---|---|---|---|---| | 4 | 0 | `0x200000` | 4 / 28 | 500 kbit/s P-bus | 0 | | 2 | 1 | `0x201000` | 3 / 27 | Middle channel; not enabled | — | | 0 | 2 | `0x202000` | 2 / 26 | Approximately 33.3 kbit/s SWCAN / I-bus | 1 | Native channel numbers and Nano channel numbers are different namespaces. The native helpers at `0x143aa` and `0x1366c` underpin the controller/IRQ map. The implemented route validates standard data frames, timing and electrical state together: - Controller 0, BTR0/BTR1 `C1/36`, standard CAN → Nano channel 0, flags zero. - Controller 2, BTR0/BTR1 `DD/36`, GPIO assignment zero and direction low bits `11`: latch low bits `10` with ID `0x100`, DLC zero selects single-wire wake; latch low bits `11` selects normal single-wire traffic. - Wake uses J2534 `SW_CAN_HV_TX=0x0400`, translated to Nano USB wire flag `0x1000`. Normal traffic uses flags zero. Unsupported combinations are rejected. This preserves the firmware's electrical intent rather than inferring wake-up solely from a CAN ID. It is not a complete physical CANdi board model. ## Tech2 ↔ CANdi serial command evidence These are serial frames, **not vehicle CAN payloads**. Complete frames sum to zero modulo 256, including the checksum. A zero-byte space-parity delimiter and receive break plus framing-error status were required at the emulated UART. | Request | Meaning | Observed reply / interpretation | |---|---|---| | `90 03 6D` | Device information | `91 03 …`, status zero, “CANdi Application” | | `80 09 01 45 85 AC` | Observed baud-change request | `81 09 00 76` | | `88 0E 6A` | Native channel 0 wake | `89 0E 00 69`: command accepted, before CAN TX confirmation | | `2E D2` | Receive-queue poll across channels | `2F D2 FF`: empty queue | | `80 0C …` | Firmware inventory request family | `81 0C …` reply family | Ellipses omit bytes and are not executable packet templates. The receive poll maps to command `0x28` with channel bits `0x06` in the MSI application's dispatch table at `0x1a5fe`, handler `0x11ab8 → 0x11892`. Logs separate serial acceptance, original firmware TX intent, USB writes, transport completion, received CAN frames, guest filter acceptance and LCD results. USB-write compatibility completion and J2534 software loopback do not measure an electrical CAN ACK. A received ECU reply supplies separate evidence. ## Read result: original Diagnostics / All / DTC / F0 The original vehicle, key-position and transport-fuse checks completed. The firmware reported ECM and TCS/ESP missing in this scan; the operator continued through its own prompt. It later requested “Turn Ignition Key to LOCK if Possible.” The physical key transition was accepted from real CIM traffic. No fabricated key-state reply or host DTC reader supplied the result. | Module on original screen | Displayed DTC | |---|---| | BCM | B0092-05 | | RRDM | B3210-06 | | RRDM | B3205-06 | | TPMM | C0777-5A | | UEC | B2575-04 | Raw SW `0x541` replies included `81 45 47 04 11 00 00 00` and terminal `81 00 00 00 17 00 00 00`. The first decodes as CIM C0547-04, status `11`. It reached the native receive filter but the guest omitted it from the displayed summary. Do not force it into a recreated screen, or call the CIM fault-free. The prior Windows ME9.6 P0411-00 result was not part of this Android scan. The successful run recorded 168 original CAN writes, 96,340 HS RX frames and 8,366 SW RX frames. These RX totals include background bus traffic, not only responses. The result appeared around 127 seconds. Both Java and Rust confirmed clean shutdown and USB release after evidence capture. ## Clear result: original Diagnostics / All / DTC / F1 This was a separate operator-requested operation with the original Yes confirmation. The clear completed vehicle, engine-running, key-position and OBD-II checks. It used GMW3110 service `04` with positive reply `44`; observed request CAN payload was `01 04` plus original padding. The `01` is the declared service length, not a second diagnostic service. The clear workflow also sends `A9 81 0A` status reads. An earlier command gate rejected that exact read and stopped a partial attempt; allowing it in the explicit clear profile enabled the original workflow to continue. Read, seed and clear profiles remain separate, enforced in both Java and Rust. CIM P-bus returned NRC `78` (response pending) before positive `44` roughly 84 seconds after the first request; ESP took roughly 34 seconds. Those waits were observed, not universal timeouts to hard-code. The firmware then requested “Turn Ignition Key to LOCK for Clearing CIM & SCL DTC's.” The physical check passed, another CIM positive reply arrived, and the original screen displayed **Vehicle DTC's Cleared**, with **OK**. Examples of positive `44` response IDs in this clear session: | Bus | Response ID | Observed module | |---|---|---| | HS | `7E8` | ECM | | HS | `643` | ESP | | HS | `645` | CIM P-bus | | SW | `641` | CIM I-bus | | SW | `642` | BCM | | SW | `64B` | RRDM | | SW | `65F` | TPMM | | SW | `64F` | UEC | There were 108 original CAN writes, including 25 physical service-04 submissions plus functional broadcasts. Positive replies covered 21 distinct **(channel, response-ID) pairs**, not 21 unique ECUs. RX totals were 167,358 HS and 13,001 SW frames. Both layers confirmed clean shutdown around 232 seconds. Padding after a reply's declared length is not part of service `44`. The final screen proves completion of this native workflow. **A fresh post-clear scan is still needed** to determine which faults return; clearing does not fix their causes. Failed startup and partial attempts are retained separately and are not counted as vehicle-wide successes. ## Other milestones and limits A separate original-firmware Android session wrote a 714-byte pre-auth SSA block with ten populated records after the LOCK/key-removal sequence. This proves collection only: that run did not process an API result or complete an unlock. No VINs, seeds, keys, raw archives or proprietary firmware are distributed here. The original 42-item engine-data page was reached, but sensor values were not validated. That investigation is paused. Chipsoft Pro / MDI transports, broader repeatability and iOS wireless are future work, not shipped compatibility claims. ## Evidence and references Private shared-core checkpoints: `0baccf2` (read) and `f459f9d` (clear), with tag `android-native-dtc-clear-2026-09-08`. Read evidence was captured in `pixel-native-dtc-20260908-232240Z`; clear evidence in `pixel-native-clear-20260908-233016Z`. Raw evidence remains private. The linked article reproduces the actual Android screenshots. The clear checkpoint passed 165 Rust tests and JVM request/command-gate checks; the subsequent observed A9-mask addition passed focused Rust/JVM checks and the ARM64 APK rebuild. A generic manual harness's incomplete/exit-3 status reflects operator stop; the fresh replies plus original LCD establish the milestones. - [NXP MC68331 user manual](https://www.nxp.com/docs/en/data-sheet/MC68331UM.pdf) - [GMW3110 (2010), hosted copy](https://studylib.net/doc/26162849/gmw3110-2010) - [J2534 v04.04 flag declarations](https://github.com/joeyoravec/j2534-logger/blob/master/ptshim32/j2534_v0404.h) Related captured command definitions are retained in the private OpenSAAB catalog: `commands/saab/check_codes_read_dtcs.yaml` and `commands/saab/clear_codes_clear_dtcs.yaml`.