Diagnostics: UDS & DoIP
UDS (Unified Diagnostic Services, ISO 14229) is the protocol every workshop scan tool speaks: read trouble codes, live data, flash firmware, run routines. Common services: ReadDTC (0x19), ReadDataByIdentifier (0x22), RoutineControl (0x31), RequestDownload (0x34). DoIP (Diagnostics over IP, ISO 13400) carries UDS over automotive Ethernet, replacing K-Line and CAN-based ISO-TP diagnostics on modern architectures. DTCs (Diagnostic Trouble Codes) are standardized fault records. A P-code in the glove box manual is a UDS concept. When you run adb shell dumpsys car_service, you’re doing the software developer’s version of the same job: asking the vehicle stack what’s wrong.
The technician plugs a scan tool into OBD-II. You SSH into QNX and grep slog2. Different tools, same question: “What’s broken, and can I fix it?” UDS is the language the industry agreed on for that conversation.
UDS: The Service Technician’s Protocol
Section titled “UDS: The Service Technician’s Protocol”UDS defines a client/server model: the tester (scan tool, factory rig, your script) sends service requests; the ECU (or gateway) responds with data or negative response codes (NRC).
| Concept | Meaning |
|---|---|
| Tester | External diagnostic client (ODIS, CANoe, custom Python script) |
| ECU / Server | Any node exposing diagnostic services (gateway, cluster, ADAS ECU) |
| SID | Service Identifier (first byte of every request, e.g., 0x22 = ReadDataByIdentifier) |
| DID | Data Identifier (which data item to read, e.g., 0xF190 = VIN) |
| NRC | Negative Response Code (why the request failed, e.g., 0x33 = SecurityAccessDenied) |
| Session | Diagnostic mode: Default, Programming, Extended (controls which services are allowed) |
Legacy transport was ISO-TP over CAN (8-byte frames, multi-frame segmentation). Modern centralized/zonal architectures use DoIP (next section), but the UDS services are identical regardless of transport.
Common UDS Services You’ll Encounter
Section titled “Common UDS Services You’ll Encounter”| Service | SID | Purpose | Workshop Example | Your Platform Equivalent |
|---|---|---|---|---|
| ReadDTCInformation | 0x19 | Read stored/pending trouble codes | “Check engine light — what’s the code?” | Gateway DTC snapshot via factory tool |
| ReadDataByIdentifier | 0x22 | Read live or stored data by DID | Read VIN, battery voltage, software version | Reading VHAL property or QNX config |
| WriteDataByIdentifier | 0x2E | Write calibration/config data | Provisioning, variant coding | Writing persistent config (often SecurityAccess-protected) |
| RoutineControl | 0x31 | Start/stop/request results of test routines | Headlight aim routine, sensor calibration | Factory test mode trigger |
| RequestDownload | 0x34 | Begin firmware download (flash programming) | ECU reflash during recall | OTA is different path, but factory flash uses this |
| TransferData | 0x36 | Send firmware data blocks | Continuation of flash | — |
| RequestTransferExit | 0x37 | Finish firmware download | End of flash session | — |
| SecurityAccess | 0x27 | Seed-key authentication for protected services | Unlock ECU for writing | Cybersecurity gate (Module 9.2) |
| ECUReset | 0x11 | Hard/soft/key-off reset | “Clear adaptations and reboot ECU” | adb reboot / QNX process restart |
ReadDTC (0x19): Reading Trouble Codes
Section titled “ReadDTC (0x19): Reading Trouble Codes”Sub-functions filter what you get:
| Sub-function | What It Returns |
|---|---|
| reportNumberOfDTCByStatusMask | Count of stored codes matching status mask |
| reportDTCByStatusMask | List of DTCs with status (test failed, pending, confirmed) |
| reportDTCSnapshotRecordByDTCNumber | Freeze-frame data captured when fault occurred |
| reportDTCExtendedDataRecordByDTCNumber | Extended fault context (occurrence count, aging) |
ReadDataByIdentifier (0x22): Live Data
Section titled “ReadDataByIdentifier (0x22): Live Data”Send: [0x22] [DID high] [DID low] → Receive: [0x62] [DID] [data bytes...]
Common DIDs (manufacturer-specific ranges apply):
| DID | Typical Content |
|---|---|
| 0xF190 | VIN |
| 0xF181 | Application software identification |
| 0xF187 | Spare part number |
| 0x010C | Engine RPM (powertrain ECUs) |
RoutineControl (0x31): Built-In Test Routines
Section titled “RoutineControl (0x31): Built-In Test Routines”Three sub-functions: startRoutine, stopRoutine, requestRoutineResults. Factory lines run these for camera calibration, speaker test, leak test. A failed routine often sets a DTC.
RequestDownload (0x34): Flash Programming
Section titled “RequestDownload (0x34): Flash Programming”Kicks off the programming session sequence: RequestDownload → TransferData (repeated) → RequestTransferExit → ECUReset. Protected by SecurityAccess and Programming Session. This is how workshop tools reflash ECUs. Distinct from cloud OTA, but same integrity concerns (signing, rollback).
UDS is a restaurant order system. The SID is the menu category (appetizers = read data, entrees = routines, dessert = clear DTCs). The DID is the specific dish. NRC 0x33 is “kitchen locked — show your staff badge” (SecurityAccess). DoIP is switching from shouting orders through a mail slot (CAN ISO-TP) to calling on a dedicated phone line (Ethernet) — same menu, better bandwidth.
DoIP: UDS Over IP
Section titled “DoIP: UDS Over IP”DoIP (ISO 13400) wraps UDS payloads in TCP/UDP over automotive Ethernet. Essential when your domain controller aggregates dozens of ECUs behind one diagnostic gateway.
| Legacy (CAN ISO-TP) | Modern (DoIP) | |
|---|---|---|
| Physical layer | CAN bus (500 kbps–1 Mbps) | 100BASE-T1 / 1000BASE-T1 Ethernet |
| Bandwidth | ~7 KB/s effective | Megabytes/sec |
| Addressing | CAN ID pairs | IP address + logical address (LA) |
| Routing | Direct or via gateway | DoIP gateway routes to internal ECUs |
| Use case | Body ECUs, legacy powertrain | Cockpit domain controller, zonal gateways, ADAS |
DoIP header structure (simplified):
| Field | Purpose |
|---|---|
| Protocol version | 0x02 (ISO 13400-2:2019) |
| Payload type | Vehicle identification, routing activation, diagnostic message |
| Logical address | Which ECU (e.g., 0x0E00 = gateway, 0x0E80 = instrument cluster) |
| UDS payload | The actual 0x22/0x19/etc. service bytes |
Routing Activation is the DoIP handshake. Tester connects to gateway IP (often 169.254.x.x link-local on OBD), sends activation request, gateway assigns diagnostic channel, then UDS flows.
DTCs: Diagnostic Trouble Codes Explained
Section titled “DTCs: Diagnostic Trouble Codes Explained”A DTC (Diagnostic Trouble Code) is a standardized fault record stored when a monitor detects a malfunction.
| DTC Format | Example | Meaning |
|---|---|---|
| P0128 | P = Powertrain | Coolant thermostat rationality |
| B0020 | B = Body | Occupant classification sensor |
| C0035 | C = Chassis | Left front wheel speed sensor |
| U0100 | U = Network | Lost communication with ECM |
Each DTC has a status byte:
| Status Bit | Meaning |
|---|---|
| Test failed | Fault currently present |
| Test failed this cycle | Failed since last power cycle |
| Pending | Detected but not yet confirmed |
| Confirmed | Stored after confirmation criteria met |
| Test not completed since last clear | Monitor hasn’t run yet |
| Warning indicator requested | Telltale/MIL should be on |
On your platform, a gateway DTC like U0140 (Lost communication with body control module) might appear in the technician’s scan tool while you simultaneously see stale signals in VHAL. Same root cause, two views.
Clearing DTCs (UDS 0x14) is not fixing the bug. Workshop “clear codes” resets monitor status. If the fault persists, the DTC returns next drive cycle. When factory asks for a DTC snapshot log, they want the pre-clear freeze frame, not your assurance that you cleared it and drove around the block.
Diagnostic Flow: End to End
Section titled “Diagnostic Flow: End to End”sequenceDiagram participant Tech as Workshop Tester<br/>(ODIS / CANoe) participant OBD as OBD-II Port participant GW as DoIP Gateway<br/>(QNX domain controller) participant Cluster as Instrument Cluster ECU participant CAN as CAN / Ethernet Bus participant BCM as Body Control Module
Tech->>OBD: Ethernet or CAN connection OBD->>GW: DoIP Routing Activation GW-->>Tech: Activation OK (logical address assigned)
Tech->>GW: UDS 0x19 ReadDTC (all ECUs via gateway) GW->>Cluster: Route UDS over internal bus Cluster-->>GW: DTC U0121 — lost comm with BCM GW-->>Tech: Aggregated DTC list
Tech->>GW: UDS 0x22 ReadDataByIdentifier (0xF190 VIN) GW-->>Tech: VIN bytes
Tech->>GW: UDS 0x27 SecurityAccess (seed-key) GW-->>Tech: Unlock for programming session
Tech->>GW: UDS 0x34 RequestDownload (BCM firmware) GW->>BCM: Route programming sequence BCM-->>GW: Transfer ready Tech->>GW: UDS 0x36 TransferData (blocks...) GW->>BCM: Flash blocks Tech->>GW: UDS 0x11 ECUReset BCM->>BCM: Reboot with new firmwareadb shell dumpsys car_service is the software equivalent of a UDS ReadDataByIdentifier session. You’re querying the vehicle abstraction layer for property values, service states, and errors without a physical scan tool.
# What's the vehicle stack reporting? (developer "scan tool")adb shell dumpsys car_service
# Specific property, like reading a DIDadb shell dumpsys car_service --services VehicleHaladb shell cmd car_service get-property-value 291504647 # VEHICLE_SPEED example ID
# QNX side equivalent: gateway logs during diagnostic sessionslog2info -w | grep -i "uds\|doip\|dtc\|diag"When a factory issue report says “DTC U0100 during routine 0x0203,” decode it:
- U0100: network communication fault (Module 9.2: could be bus-off OR gateway software bug)
- Routine 0x0203: look up in OEM diagnostic spec (RoutineControl)
- Reproduce: connect CANoe/DoIP tester, run same routine, capture gateway routing logs on QNX
Your bug isn’t “infotainment” if the DTC is set by the gateway ECU during a UDS session. That’s QNX diagnostic stack territory, even if the symptom appears in Android.
UDS Sessions and SecurityAccess
UDS diagnostic sessions gate which services are legal:
| Session | SID 0x10 Sub | Typical Access |
|---|---|---|
| Default | 0x01 | ReadDTC, ReadData (read-only) |
| Programming | 0x02 | RequestDownload, TransferData (flash) |
| Extended | 0x03 | RoutineControl, WriteData (factory calibration) |
Entering Programming or Extended session usually requires SecurityAccess (0x27). ECU sends a seed, tester computes key from OEM algorithm. This is ISO 21434’s diagnostic-layer lock. Leaked seed-key algorithms are a TARA-critical asset. They enable unauthorized reflashing via OBD.
Module 1.2 noted CAN IDs aren’t IP addresses. UDS over ISO-TP was the diagnostic answer on CAN. Module 2’s centralized architecture requires DoIP when one gateway serves 70+ logical ECUs. Module 4’s AUTOSAR DCM (Diagnostic Communication Manager) module implements UDS on Classic AUTOSAR ECUs. Module 6.3’s VHAL is the AAOS-side mirror of diagnostic data identifiers. Module 9.2’s OBD-II attack surface is where UDS SecurityAccess protects you.
Takeaways
Section titled “Takeaways”- UDS (ISO 14229): standardized diagnostic services (0x19, 0x22, 0x31, 0x34…).
- DoIP (ISO 13400): UDS over automotive Ethernet via gateway routing.
- DTCs: P/B/C/U codes with status bytes; freeze frames capture fault context.
- SecurityAccess protects write/flash operations (cybersecurity meets diagnostics).
dumpsys car_serviceis your developer diagnostic console, same intent as a scan tool.
Check Your Understanding
1. What is the primary role of DoIP (ISO 13400) in modern vehicle diagnostics?
2. A workshop tool sends UDS service 0x22 with DID 0xF190. What is it requesting?
3. How does `adb shell dumpsys car_service` relate to UDS diagnostics?