Electronics Guide

Vehicle Diagnostic Protocols

When a technician plugs a scan tool into a vehicle, the tool does not measure a sensor. It sends a byte sequence to a piece of software running inside an electronic control unit, and the control unit answers with another byte sequence. Everything the technician sees afterward, from a live coolant temperature to a stored fault code to a progress bar during a software update, is an interpretation of those exchanges. Vehicle diagnostic protocols are the rules that govern them: what a request looks like, how a control unit refuses one, how a message longer than a single bus frame gets across, how a tester finds the right control unit among the forty or more in a modern car, and how a tool vendor knows what any of the returned bytes mean.

This article covers the manufacturer diagnostic and reprogramming stack. The companion article on on-board diagnostics (OBD) covers the legislated emissions system: the numbered OBD-II service modes, the standardized parameter identifiers, the readiness monitors that an inspection program checks, and the malfunction indicator lamp. That system is deliberately small, because its purpose is to guarantee that any tool can read emissions data from any vehicle. The stack described here is the much larger one that sits alongside it and that manufacturers, suppliers, and repair networks actually use for everything else: reading a fault out of a body controller, commanding a fuel injector open on a bench, coding a replacement module to a specific vehicle, calibrating a radar sensor after a windshield replacement, and writing a new software image into flash memory. The legislated system is a small, mandated island inside this larger territory, and the two increasingly share the same underlying protocol.

The stack has four distinct layers, and confusing them is the most common source of trouble. At the top sits Unified Diagnostic Services, standardized as ISO 14229, which defines what a request means. Beneath it sits a transport layer, either ISO 15765-2 for diagnostics carried on a Controller Area Network or ISO 13400 for diagnostics carried over Internet Protocol, which defines how a request that does not fit in one frame gets delivered. Beside both sits a description layer, ODX (ISO 22901), which is a machine-readable statement of exactly which services, identifiers, and fault codes a given control unit supports and how to convert its raw bytes into engineering units. Above that sits a sequence layer, OTX (ISO 13209), which describes test and service procedures as executable, portable programs rather than as prose in a workshop manual.

Understanding this stack matters well beyond the repair bay. The same services drive end-of-line testing in the assembly plant, hardware-in-the-loop validation in the development lab, warranty analysis in the field, and over-the-air update campaigns after the vehicle is sold. It also carries the most consequential security question in vehicle electronics, because a protocol that can erase and rewrite the memory of a braking controller is, by construction, the most dangerous interface a vehicle exposes.

From Legislated Modes to a Manufacturer Protocol Stack

Through the 1980s, every manufacturer invented its own diagnostic interface. Connectors differed, signaling differed, and the meaning of a blinking lamp differed. Regulation forced partial convergence: emissions diagnostics acquired a standard connector defined by SAE J1962, a small set of standard signaling options, and a fixed catalog of service modes. That convergence solved the regulator's problem and the independent shop's minimum need, but it did nothing for the manufacturer, whose own service network needed access to hundreds of parameters and dozens of actuator tests in systems that emissions law never touched.

The bridge came from Keyword Protocol 2000, published as ISO 14230. KWP2000 introduced the structural ideas that survive today: a request begins with a service identifier byte, a positive response echoes that identifier with a fixed offset, and a refusal takes a distinct negative-response form that names both the service and the reason. It was, however, tied closely to the K-line serial interface for which it was designed.

ISO 14229 generalized that model and cut it loose from any particular bus. Its first part specifies the application layer alone: the services, their parameters, their response formats, and the negative response codes. Later parts bind that application layer to specific networks. ISO 14229-3 defines UDS on CAN, ISO 14229-4 defines UDS on FlexRay, ISO 14229-5 defines UDS on Internet Protocol, ISO 14229-6 defines UDS on K-line, and ISO 14229-7 defines UDS on LIN. A service such as ReadDataByIdentifier means precisely the same thing on every one of them. This separation is the single most useful property of the standard: a diagnostic application written against ISO 14229-1 does not change when a vehicle platform migrates from CAN to automotive Ethernet, and only the transport binding underneath it is replaced.

On the vehicle side, the services are usually not hand-written. AUTOSAR, the layered software architecture that most manufacturers require of their suppliers, provides a Diagnostic Communication Manager that implements the ISO 14229 service handlers and a Diagnostic Event Manager that owns fault memory, its aging and healing rules, and its snapshot capture. An application developer registers a data identifier or a monitored event with these modules through a configuration file, and the protocol behavior follows from the standard rather than from local invention. The practical consequence is that most control units on most vehicles behave similarly at the protocol level even when their functions have nothing in common.

The legislated world has since begun migrating onto this same foundation. ISO 27145, the world-wide harmonized OBD series referenced by United Nations global technical regulation work, expresses emissions diagnostics as UDS services carried over ISO 15765-2 or ISO 13400, with a common data dictionary in place of the older mode-and-PID catalog. SAE published J1979-2, titled "E/E Diagnostic Test Modes: OBDonUDS," in April 2021 and revised it in April 2026. The long-term direction is one protocol serving both purposes, with the legislated subset defined as a required profile rather than as a separate language.

The Request and Response Model of Unified Diagnostic Services

A UDS request is a byte string. The first byte is the service identifier, commonly abbreviated SID. Many services follow it with a subfunction byte that selects a variant of the service, and then with service-specific parameters. A request to read a data record, for example, consists of the identifier 0x22 followed by a two-byte data identifier.

A successful response echoes the request service identifier with 0x40 added to it, followed by the returned data. A request beginning with 0x22 therefore produces a response beginning with 0x62, and a request beginning with 0x31 produces a response beginning with 0x71. This offset makes responses trivially recognizable in a bus trace, which is why protocol analysts learn it early.

A refusal takes a completely different shape. The control unit answers with 0x7F, then the service identifier of the request that failed, then a single negative response code that states why. Three bytes carry the whole outcome. This structure is why a scan tool can report a meaningful error for a service it does not itself understand.

Where a service takes a subfunction byte, the most significant bit of that byte carries a separate meaning. Setting it, which in practice means adding 0x80 to the subfunction value, requests that the control unit suppress the positive response and answer only if something goes wrong. This suppress-positive-response indication exists to save bus bandwidth on high-frequency housekeeping traffic, and it is the reason a tester-present message is almost always seen on the wire as the two bytes 0x3E 0x80 with nothing coming back.

Requests reach control units by one of two addressing modes. Physical addressing targets a single control unit, and exactly one response is expected. Functional addressing broadcasts a request to every control unit that implements the addressed function, and any number of responses may arrive, each from a different source address. Functional addressing is how a tester asks "who is out there" or clears fault memory across a whole vehicle in one message, and it is how legislated emissions requests reach every emissions-relevant module without the tool knowing the vehicle architecture. Functional requests must fit in a single transport frame, because the flow-control mechanism described later cannot arbitrate between many simultaneous responders.

Negative Response Codes

The negative response code catalog is small enough to memorize and is the fastest diagnostic aid in the protocol. A code of 0x11 means the service is not supported at all; 0x12 means the service exists but the requested subfunction does not; 0x31 means the request was well formed but a parameter fell outside a supported range, which in practice usually means the data identifier or routine identifier does not exist in this control unit. A code of 0x13 means the message length was wrong or the format was invalid, which is almost always a tool-side defect rather than a vehicle fault.

Another group reports that the request was understood but is not permitted right now. A code of 0x7F means the service is not supported in the active diagnostic session, and 0x7E means the subfunction is not supported in the active session; both point at a missing session change. A code of 0x33 means security access has not been granted. A code of 0x22 means conditions are not correct, which is the standard way a control unit refuses an actuator test because the engine is running or the vehicle is moving. A code of 0x24 means a request sequence error, typically a transfer-data request that arrived without a preceding request-download.

The security-related codes form their own family: 0x35 for an invalid key, 0x36 for exceeding the permitted number of attempts, and 0x37 for a required time delay that has not yet expired. The programming family includes 0x70 for a rejected download or upload, 0x72 for a general programming failure, and 0x73 for a wrong block sequence counter. A tool that reports these codes verbatim, rather than translating them into a generic "communication error," saves an enormous amount of diagnostic time.

Response Pending and the Timing Model

Some operations take far longer than a control unit is allowed to leave a request unanswered. Erasing a flash sector, running a self-test, or computing a checksum over a megabyte of memory cannot complete within a normal response window. The protocol solves this with a special negative response code, 0x78, whose name is requestCorrectlyReceived-ResponsePending. Its meaning is precise: the request was valid and is being worked on, so restart the timeout with the extended value and keep waiting. The control unit may repeat it as often as necessary and finally sends either the real positive response or a genuine negative one.

Two timers govern this. The first, usually written P2, is the ordinary maximum time the tester waits for a first response; fifty milliseconds is a common configured value. The second, written P2 star, is the longer timeout that applies after a response-pending message arrives; five seconds is a common configured value. The actual values are vehicle-specific and are reported by the control unit in the positive response to a session-control request, so a well-written tester reads them rather than assuming them.

A third timer, usually written S3, governs the other direction. If a control unit that has been placed in a non-default session hears nothing from the tester for longer than this period, it returns to the default session on its own, discarding any security access that had been granted. A value of five seconds is common. This timeout is a safety feature: it guarantees that a vehicle cannot be left indefinitely in a state where its fault detection is suppressed or its actuators are under external control simply because a technician unplugged a cable.

Session Control, ECU Reset, and Tester Present

DiagnosticSessionControl, service 0x10, is the first request in almost every diagnostic exchange. A session is a mode that determines which services and which data the control unit will accept. The default session, subfunction 0x01, is what the control unit runs in during normal driving; it permits reading but little else. The programming session, subfunction 0x02, prepares the unit for a software download and frequently causes it to restart into a bootloader with its normal application suspended. The extended diagnostic session, subfunction 0x03, unlocks the wider service set used for actuator tests, coding, and detailed fault memory access. A safety-system diagnostic session, subfunction 0x04, exists for functions with safety implications that require an additional deliberate step.

The positive response to a session change carries the timing parameters for that session, so the tester learns the applicable P2 and P2 star values at exactly the moment they begin to matter. Sessions are also the mechanism behind the 0x7E and 0x7F negative responses: a service that returns 0x7F in the default session frequently succeeds immediately after a switch to the extended session, and a large share of apparent tool incompatibility resolves to a missing session change.

ECUReset, service 0x11, restarts a control unit under tester command. Subfunction 0x01 requests a hard reset equivalent to a power cycle, 0x02 simulates a key-off then key-on cycle, and 0x03 requests a soft reset that reinitializes the application without cycling hardware. Additional subfunctions enable and disable rapid power shutdown, which lets a tester tell a control unit to finish its shutdown housekeeping quickly rather than lingering on the bus. Reset is not a cosmetic operation. It is the step that makes newly written coding data take effect, and it is the final step of a reprogramming sequence.

TesterPresent, service 0x3E, exists solely to restart the S3 timer. Sent typically every two seconds with the suppress-positive-response bit set, it tells every control unit that the tester is still connected and that any non-default session should be held open. Losing this heartbeat during a long operation is a classic field failure: a control unit silently drops back to the default session, the next request returns 0x33 because security access evaporated with it, and the tool reports an error that appears to have nothing to do with a missed message two seconds earlier.

Two further services belong to the same housekeeping family. CommunicationControl, service 0x28, tells a control unit to stop transmitting or receiving its normal application messages, which is how a tester silences the network before reprogramming so that the target is not interrupted by periodic traffic. ControlDTCSetting, service 0x85, tells control units to stop storing new fault codes for the duration of the work. Without it, disconnecting a sensor for a test or holding a module in reset during a flash writes a page of spurious faults that a technician must then clear and, worse, that a customer may see as a warning lamp on the drive home.

Security Access and the Seed-and-Key Exchange

SecurityAccess, service 0x27, gates the services that can change a vehicle. Its structure is a challenge-response exchange with a deliberately simple wire format. The tester sends 0x27 with an odd subfunction value to request a seed. The control unit replies with a random or pseudo-random value, typically two to four bytes, though longer seeds are used. The tester computes a key from that seed using an algorithm and a secret constant it is expected to hold, and sends the key back with 0x27 and the next even subfunction value. The control unit performs the same computation and compares. A match unlocks the corresponding security level; a mismatch returns 0x35.

Subfunction pairs allow several independent levels, so that reading protected data, performing actuator tests, and reprogramming can require different secrets. A control unit that is already unlocked normally answers a seed request with a seed of all zeros, which is the conventional signal that no further authentication is needed.

The protection against brute force is a failed-attempt counter with an enforced delay. After a small number of wrong keys, typically three, the control unit returns 0x36 and refuses further attempts until a delay expires, reporting 0x37 in the meantime. Critically, a correct implementation stores this counter in non-volatile memory, so that power-cycling the module does not reset it. Implementations that keep the counter in RAM are trivially defeated by a tool that resets the module between guesses, and this has been a recurring real-world weakness.

The deeper weakness is structural. The seed-and-key exchange is symmetric: the tool and the control unit share the same secret. Every tool authorized to reprogram a given model must therefore hold the manufacturer's key material, which means the secret is distributed to thousands of workshops and embedded in software that runs on ordinary computers. Extraction from a tool binary or from a control unit's own firmware has been demonstrated repeatedly, and algorithms for many older platforms circulate openly. Short seeds compound the problem, since a two-byte seed admits only sixty-five thousand possible challenges and invites precomputation. The mechanism was designed to keep casual tampering out, not to withstand a determined analyst with the tool in hand.

The 2020 edition of ISO 14229-1 addresses this with a new Authentication service, identifier 0x29, built on public-key cryptography rather than a shared secret. In place of a seed and a key, the tester presents an X.509 certificate, proves possession of the corresponding private key by signing a challenge, and receives access rights determined by the roles named in the certificate. The advantages are the ordinary advantages of asymmetric cryptography in a fleet: the control unit holds only a public trust anchor and never a secret that could be extracted from it, a compromised tool can have its certificate revoked without touching a single vehicle, and different tools can be granted different privileges from the same infrastructure. A matching negative response code, 0x34, reports that authentication is required. Migration is gradual, because it presupposes a working public-key infrastructure across a manufacturer's entire service network, but new platforms increasingly require it for anything that writes memory.

Reading and Writing Data by Identifier

ReadDataByIdentifier, service 0x22, is the workhorse. A request supplies one or more two-byte data identifiers, and the response returns the corresponding records concatenated in the order requested. The identifier space is enormous, which is the point: a manufacturer can expose any internal quantity a service engineer might ever need without extending the protocol. Live sensor values, computed torque estimates, adaptation values, error counters, network statistics, and configuration words are all reachable through the same service.

Part of the identifier space is standardized. The range beginning at 0xF180 holds identification records: the vehicle identification number lives at 0xF190, with neighboring identifiers holding the manufacturer's spare-part number, hardware and software version numbers, the control unit serial number, and the identifier of the currently active diagnostic session. These fixed assignments let a tool inventory a vehicle before it knows anything else about it, which is exactly what a workshop system does when a car arrives: read the vehicle identification number, read every module's part and software numbers, and compare the result against the manufacturer's records to find modules running outdated software or parts that do not belong.

WriteDataByIdentifier, service 0x2E, is the inverse and is usually gated behind security access. It is the mechanism for variant coding, in which a replacement module is told what vehicle it is now part of and which options that vehicle has. It writes the vehicle identification number into a new module, it configures a body controller for the correct market and lighting regulations, and it records the reprogramming fingerprint, a small record of the date and the identity of the tester that performed the last software change, which manufacturers use for warranty and traceability purposes.

Two lower-level services read and write raw memory: ReadMemoryByAddress, service 0x23, and WriteMemoryByAddress, service 0x3D. They take an address and a length in a format the request itself declares. They are indispensable during development and are the reason a manufacturer's security policy must treat diagnostic access seriously, since an unguarded WriteMemoryByAddress is an arbitrary-write primitive delivered over a connector under the dashboard. Production configurations normally restrict or remove them.

Three further services optimize repeated reading. ReadDataByPeriodicIdentifier, service 0x2A, asks a control unit to transmit a record repeatedly at a slow, medium, or fast rate without further requests, which is how a tool graphs a live signal without saturating the bus with request traffic. DynamicallyDefineDataIdentifier, service 0x2C, composes a new identifier out of pieces of existing ones, so that a tester can gather several scattered values into a single efficient read. ResponseOnEvent, service 0x86, arranges for a control unit to send a response when a condition occurs rather than when it is asked, turning polling into notification.

Every one of these services returns raw bytes. The protocol says nothing about whether a given two-byte field is a temperature in quarter degrees with an offset of forty, an enumerated gear position, or a bit field of valve states. That knowledge lives in the description layer, which is why ODX exists and why a scan tool without the right data file can talk to a control unit perfectly and still display nothing useful.

Fault Memory and ReadDTCInformation

ReadDTCInformation, service 0x19, is the richest service in the standard, and its complexity reflects how much a modern fault memory actually holds. The service takes a subfunction that selects a report type. Subfunction 0x01 returns a count of matching fault codes, 0x02 returns the codes themselves, 0x04 returns a stored snapshot for a specified code, 0x06 returns extended data records for a specified code, and 0x0A returns every code the control unit is capable of reporting whether or not it is currently set. That last report is what a tool uses to build a complete picture of a module's diagnostic coverage without a data file.

The Diagnostic Trouble Code Numbering Scheme

The familiar five-character code such as P0301 or C1234 comes from SAE J2012 and its international counterpart ISO 15031-6. The first character names the system group: P for powertrain, C for chassis, B for body, and U for network and communication faults. The first digit indicates ownership, with zero denoting a code defined by the standard and identical across all manufacturers, and one denoting a manufacturer-defined code whose meaning must be looked up for that make. The remaining three hexadecimal digits identify the specific fault.

UDS carries this as three binary bytes rather than as text. The first two bytes encode the letter and the four digits, with the system-group letter derived from the top two bits. The third byte is a failure-type byte, drawn from a list in an annex to ISO 14229-1, which distinguishes the manner of failure: a short to ground reads differently from an open circuit, an out-of-range signal, an erratic signal, or a missing network message. This third byte is a genuine improvement over the legislated five-character format, because it separates the affected component from the nature of its failure. A workshop system can therefore route "circuit open" and "signal implausible" on the same component to different diagnostic procedures, which a single opaque code cannot support.

The Status Mask and the Availability Mask

Each stored code carries an eight-bit status byte, and understanding it separates a competent diagnosis from a guess. Bit 0 reports that the test failed the last time it ran. Bit 1 reports that it failed at least once during the current operation cycle. Bit 2 marks the code as pending, meaning a fault has been detected but has not yet met the criteria for confirmation. Bit 3 marks it confirmed, meaning it has met those criteria and is stored as a genuine fault. Bit 4 reports that the test has not completed since fault memory was last cleared, and bit 5 reports that it has failed at some point since that clearing. Bit 6 reports that the test has not completed during the current operation cycle. Bit 7 requests a warning indicator, which is the bit that drives a lamp on the instrument cluster.

The distinction between bits 0 and 3 is the one that matters most in practice. A code with bit 3 set but bit 0 clear describes a fault that was confirmed at some point and is not present right now: an intermittent fault, the hardest category to chase. A code with both set is a fault present at this moment, and the technician can measure it. A code with bit 4 set means the relevant test has not run at all, so its absence proves nothing.

A tester requests codes by supplying a status mask, and the control unit returns only codes whose status byte shares at least one set bit with it. This is how a tool asks for "confirmed faults only" rather than downloading everything. The complementary mechanism is the status availability mask, returned at the head of the response, which tells the tester which of the eight bits this control unit actually maintains. Not every implementation supports every bit, and a tester that filters on an unsupported bit will silently receive nothing. Reading the availability mask first, and restricting queries to the bits it advertises, is the correct discipline and a frequent omission in tools that work on one manufacturer and fail on another.

Snapshots and Extended Data

A fault code alone rarely explains itself. UDS therefore stores two kinds of accompanying evidence. A snapshot record, the manufacturer-diagnostic analogue of the emissions freeze frame, captures a set of operating conditions at the moment the fault was recorded: engine speed, vehicle speed, coolant temperature, battery voltage, ambient temperature, throttle position, odometer reading, and whatever else the responsible engineer specified. Because the snapshot content is defined per control unit rather than by the standard, it can be far more relevant than a generic freeze frame, and the composition of each record is one of the things ODX describes.

Extended data records hold counters and history rather than a moment. Typical contents include the number of operation cycles since the fault first occurred, the number since it last occurred, an occurrence counter, the odometer reading at first and most recent occurrence, and an aging counter. These transform a fault list into a timeline. A code with an occurrence count of one and a first-occurrence odometer reading twenty thousand kilometers in the past is a different problem from the same code occurring on every drive cycle for the last week, and the extended data is where that difference becomes visible.

Fault memory also ages. A confirmed code whose test passes for a defined number of consecutive operation cycles is progressively healed and eventually deleted, so that a repaired fault does not linger forever. ClearDiagnosticInformation, service 0x14, erases codes on demand, taking a three-byte group parameter in which a value of all ones clears every group. Clearing is not a repair, and clearing before recording the status bytes, snapshots, and extended data destroys precisely the evidence needed to diagnose an intermittent fault. Disciplined practice reads and stores everything first.

Input/Output Control and Routine Control

Reading is only half of diagnosis. The other half is making the vehicle do something on command so that the result can be observed, and two services provide it.

InputOutputControlByIdentifier, service 0x2F, seizes control of a signal that a control unit normally owns. The request names a data identifier and a control option. Option 0x00 returns control to the control unit, 0x01 resets the signal to its default, 0x02 freezes it at its present value, and 0x03 applies a short-term adjustment to a value the tester supplies. Where one identifier covers several signals, an accompanying enable mask selects which of them the request affects. This is the service behind every actuator test a technician runs: commanding a cooling fan on, sweeping an instrument gauge, cycling an anti-lock brake solenoid, driving an injector, or forcing an exhaust gas recirculation valve to a commanded position while watching the resulting sensor reading.

Control is deliberately temporary. It ends when the session ends, when the tester heartbeat stops, or when the control unit decides that conditions no longer permit it. Preconditions are enforced by the control unit, not by the tool, and a refusal arrives as negative response code 0x22. A brake actuator test that is refused because the vehicle is moving is the system working correctly, and a tool that presents that refusal as a fault misleads the technician.

RoutineControl, service 0x31, invokes a named procedure inside the control unit. A subfunction of 0x01 starts a routine, 0x02 stops it, and 0x03 requests its results; a two-byte routine identifier selects which one, and optional parameters go with the request. The service is intentionally open-ended, and manufacturers use it for the operations that do not fit any other shape: erasing a flash sector, verifying a checksum over freshly programmed memory, checking programming dependencies across modules, running a built-in self-test, learning a throttle body's closed position, bleeding a hydraulic brake circuit through the anti-lock pump, initiating a diesel particulate filter regeneration, or starting a sensor calibration.

Routines that take real time interact with the timing model described earlier. A control unit either holds the request open with repeated 0x78 responses until the routine finishes, or it returns immediately and requires the tester to poll with subfunction 0x03 until the results are available. Both patterns appear in production, and a tester must handle each. Long routines are also where a lost tester-present heartbeat does the most damage, since a session timeout in the middle of a flash-erase routine can leave a module in an unusable state.

Flash Reprogramming as a Diagnostic Service

The most consequential design decision in UDS is that software download is not a separate protocol. It is a group of ordinary diagnostic services, reachable through the same connector, the same transport, and the same session mechanism as reading a temperature. The reasoning is practical: the tester is already connected, already authenticated, and already able to address the target module, so building a second channel would duplicate all of that and double the attack surface.

RequestDownload, service 0x34, opens a transfer from tester to control unit. The request carries a data-format identifier that states whether the payload is compressed or encrypted, an address-and-length format identifier that states how many bytes the following address and size fields occupy, and then the memory address and the number of bytes to be written. The response is the crucial part: it returns the maximum number of bytes the control unit can accept in a single transfer, which the tester must respect. This value is a property of the target's receive buffer, and it varies widely between modules on the same vehicle.

TransferData, service 0x36, carries the payload in blocks. Each request begins with a block sequence counter that starts at one, increments with each block, and wraps from 255 back to zero. The counter exists so that a lost or duplicated block is detected rather than silently written to the wrong place; a mismatch returns negative response code 0x73. RequestTransferExit, service 0x37, closes the transfer and gives the control unit a chance to report a problem it discovered along the way. RequestUpload, service 0x35, is the mirror image for reading memory out, and RequestFileTransfer, service 0x38, extends the same pattern to control units that expose a file system rather than a flat address space, which is increasingly common in infotainment and driver-assistance domains.

A complete reprogramming sequence chains these together in a fixed order. The tester first checks preconditions, often with a routine that asks the vehicle whether programming is permissible given battery voltage and ignition state. It suppresses fault storage with service 0x85 and silences application messaging with service 0x28, then enters the programming session with service 0x10. That session change typically causes the target to restart into a bootloader, a small resident program whose only job is to receive software, because a control unit cannot erase the flash sector it is executing from. Security access follows with service 0x27 or authentication with service 0x29. The tester writes a fingerprint with service 0x2E, then starts an erase routine with service 0x31, then performs the download with services 0x34, 0x36, and 0x37. Afterward it runs a routine to verify a checksum or cryptographic signature over the written memory, and another to check that the new software is compatible with the software in neighboring modules. Only then does it reset the module with service 0x11, return to the default session, re-enable communication and fault storage, and clear the codes the operation created.

The failure modes are unforgiving. A power interruption between the erase and the successful verification leaves a module with no valid application, recoverable only because the bootloader survives in a protected sector and can be re-entered on the next power-up. This is why workshops connect a stabilized power supply, often called a battery support unit, before any flash operation, and why manufacturers specify minimum voltages that a routine actually checks. Signature verification before activation is the corresponding software safeguard: a module that will only execute an image signed by the manufacturer cannot be permanently subverted by an interrupted or hostile download, though it can certainly be rendered temporarily inoperative.

Newer architectures reduce the exposure further with dual-bank flash, in which the new image is written to an inactive bank while the current one continues to run, and activation is a single atomic switch at the next reset with automatic rollback if the new image fails to start. This is the same mechanism that makes over-the-air updates practical, and it changes the risk profile of an update from a several-minute window of vulnerability to a single reboot.

The Transport Layer: Diagnostics on CAN

A classical CAN frame carries at most eight bytes of data, and CAN with flexible data rate raises that to sixty-four. A UDS response containing a list of forty fault codes with their status bytes, or a block of flash data, is far larger. ISO 15765-2, universally called ISO-TP, is the transport protocol that segments long messages, reassembles them, and paces the flow so that the receiver is not overrun. It is a small standard, and it is where most integration problems actually live.

Frame Types

Every ISO-TP frame begins with protocol control information, and the top four bits of the first byte identify one of four types.

A single frame, type 0, carries a complete short message. On classical CAN, the remaining four bits hold the payload length, allowing up to seven bytes of diagnostic data in an eight-byte frame, or six when the addressing scheme consumes a byte. The 2016 revision of the standard added an escape mechanism for CAN FD in which a length nibble of zero indicates that the true length follows in the next byte, permitting single frames of up to sixty-two bytes. This alone eliminates segmentation for the great majority of everyday requests on a CAN FD network.

A first frame, type 1, begins a segmented message and declares the total length. Twelve bits are available for that length, giving a maximum of 4,095 bytes; the same 2016 revision added an escape in which a declared length of zero is followed by a thirty-two-bit length field, lifting the ceiling into the gigabyte range so that a flash image can be transferred as one logical message.

Consecutive frames, type 2, carry the remainder. Each holds a four-bit sequence number that starts at one for the first consecutive frame and wraps from fifteen back to zero. The receiver checks this number and abandons the transfer on a mismatch. Four bits is a deliberately cheap mechanism: it detects loss and reordering without a per-frame acknowledgment, which CAN does not need because its data link layer already guarantees delivery or signals an error.

A flow control frame, type 3, travels in the opposite direction and is the heart of the protocol.

Flow Control, Block Size, and Separation Time

After receiving a first frame, the receiver sends a flow control frame before the sender may continue. It contains three fields. The flow status nibble is zero to continue sending, one to wait, or two to signal that the message overflows the receiver's buffer and the transfer must be abandoned. The block size byte states how many consecutive frames the sender may transmit before waiting for another flow control frame; a value of zero means send everything remaining without further permission. The separation time byte states the minimum gap between consecutive frames, encoded so that values from 0x00 to 0x7F mean zero to 127 milliseconds and values from 0xF1 to 0xF9 mean 100 to 900 microseconds.

These two parameters are the entire flow control policy, and they are chosen by the receiver because only the receiver knows its own limits. A small microcontroller with a two-frame buffer sets a block size of two and a separation time of several milliseconds. A gateway with ample memory sets a block size of zero and a separation time of zero, and the transfer runs at bus speed. The same tool talking to both must adapt, and it must adapt per message rather than per vehicle, because different modules on one bus advertise different values.

A set of network layer timers bounds every wait. The interval allowed between the first frame and the arrival of flow control, and the interval allowed between consecutive frames, are each commonly one second. Exceeding either aborts the transfer. These timers are generous by design, because they must tolerate a heavily loaded bus on which a low-priority diagnostic frame may lose arbitration repeatedly.

The standard also defines several addressing formats. Normal addressing gives each direction its own CAN identifier and uses all eight data bytes for the transport protocol. Extended addressing spends the first data byte on a target address, leaving seven. Mixed addressing combines a structured identifier with an address byte. ISO 15765-4 pins these choices down for legislated diagnostics, specifying the bit rates, an eleven-bit functional request identifier of 0x7DF, physical request identifiers from 0x7E0 to 0x7E7, and matching response identifiers from 0x7E8 to 0x7EF. Manufacturer diagnostics use their own identifier assignments, which is why a generic tool sees emissions data on any vehicle and manufacturer data on none.

Where Integration Actually Fails

Application-layer bugs are usually obvious, because a wrong service identifier produces a clear negative response. Transport-layer bugs are subtle, intermittent, and expensive, and a few patterns account for most of them.

Separation time is misread more often than any other field. A sender that treats a separation time of 0xF1 as 241 milliseconds instead of 100 microseconds turns a one-second flash transfer into an operation that times out. A sender that ignores separation time entirely works perfectly on a fast module and drops frames on a slow one, which produces a defect that appears only on certain vehicles or only when the bus is busy.

Padding is the second pattern. Some implementations require every CAN frame to be eight bytes, padding short frames with a fixed filler value, and some reject padded frames or misinterpret the filler. On CAN FD the equivalent problem is data length code rounding, since CAN FD frames jump from sixteen to twenty, twenty-four, thirty-two, forty-eight, and sixty-four bytes, so a payload of thirty-six bytes must be padded to forty-eight and the receiver must trust the declared length rather than the frame size.

Buffer limits produce failures that look like corruption. A receiver that advertises a block size larger than it can hold, or a sender that ignores an overflow flow status, loses data in the middle of long messages. Gateways add another layer, because a message crossing from one bus segment to another is reassembled and re-segmented, and the gateway's own block size and separation time may be more restrictive than either endpoint. A transfer that succeeds when the tool is connected directly to a module and fails through the vehicle's gateway is almost always this.

Finally, addressing format mismatches cause silence rather than errors. A tester using normal addressing against a module expecting extended addressing sends frames whose first data byte the module reads as a target address, and the module simply ignores everything. No negative response arrives, because from the module's point of view no request was ever made. The practical lesson is that a bus trace showing correct-looking traffic and no reply is a transport-layer question, not an application-layer one, and time spent checking service identifiers is time wasted.

Diagnostics over Internet Protocol

ISO 13400 defines Diagnostics over Internet Protocol, universally abbreviated DoIP, which carries the same UDS application layer over TCP/IP on automotive Ethernet. It is not a replacement for the application layer and does not change a single service. It replaces the transport underneath, and in doing so it changes what is practical.

The series has several parts. The general information and use-case definition sits in part 1, the transport and network layer services in part 2, the wired vehicle interface based on IEEE 802.3 in part 3, and an Ethernet-based high-speed data link connector in part 4. Part 3 is what allows Ethernet to share the existing J1962 diagnostic connector: it specifies an activation line on pin 8 that the external tester asserts to tell the vehicle to switch the connector into Ethernet mode, and it defines two alternative pin-assignment options so that manufacturers already using certain discretionary pins for their own purposes can avoid a conflict. Part 4 defines a separate, dedicated connector for cases where the J1962 connector is not appropriate.

Discovery and Routing Activation

An Ethernet tester cannot simply start sending diagnostic requests, because it does not know the vehicle's IP address. DoIP therefore begins with discovery over UDP on port 13400. A vehicle that powers up sends a vehicle announcement message three times at short intervals, carrying its vehicle identification number, its logical address, and an entity identifier. A tester that arrives later sends a vehicle identification request, either as a general broadcast or qualified by a specific vehicle identification number or entity identifier, and receives the same information in reply. This is a genuine advantage over CAN, where a tester must guess at identifiers; here the vehicle introduces itself.

Diagnostic traffic then runs over TCP, also on port 13400, with the 2019 edition adding TLS on port 3496 for secured sessions. Before any diagnostic message may pass, the tester must send a routing activation request naming its own source address and an activation type, and receive a positive routing activation response. This step is the vehicle's admission control. It can reject an unknown source address, reject a tester because all its diagnostic sockets are already in use, reject a second tester attempting to use an address already registered on another socket, or reject a request that lacks required authentication. Routing activation is the natural place to enforce a security policy, because it happens once per connection and before anything else.

Every DoIP message shares a generic header containing a protocol version, that version's bitwise inverse as a sanity check, a two-byte payload type, and a four-byte payload length. Payload types distinguish vehicle identification requests and responses, routing activation requests and responses, alive check requests and responses, entity status requests, diagnostic power mode requests, and the diagnostic messages themselves along with their positive and negative acknowledgments. The alive check exists because TCP connections can be abandoned without closing; an entity that suspects a stale socket asks, and frees the socket if no answer arrives. The entity status request lets a tester ask how many concurrent connections a gateway supports and how many are free, which is exactly what a workshop with several tools on one vehicle needs to know.

Logical Addressing and the Gateway

DoIP separates the network address from the diagnostic address. Every diagnostic message carries a two-byte logical source address and a two-byte logical target address, and these are independent of IP addresses. A range beginning at 0x0E00 is reserved for external test equipment, and manufacturers assign the remaining ranges to their own control units and functional groups.

This indirection is what makes the architecture work. A vehicle exposes one DoIP entity, normally the central gateway, at a single IP address. Behind it sit dozens of control units, most of them still on CAN, LIN, or FlexRay rather than on Ethernet. The tester opens one TCP connection and addresses any of them by logical address; the gateway examines the target address, looks up the route, and forwards the payload onto the appropriate internal bus, performing ISO 15765-2 segmentation on the way in and reassembly on the way back. From the tester's perspective there is one connection and many addressable targets. From a legacy control unit's perspective nothing has changed at all: it still receives ordinary segmented CAN traffic and has no knowledge that the request originated on Ethernet.

The Bandwidth Argument

The reason for all this machinery is arithmetic. A diagnostic CAN bus commonly runs at 500 kilobits per second. After frame overhead and the seven-byte payload of a consecutive frame, sustained throughput of roughly forty kilobytes per second is a realistic figure, and separation times enforced by slow receivers push it lower. A one-hundred-megabyte software image at forty kilobytes per second takes about forty minutes. A vehicle with several such modules cannot be updated in a service appointment, and a factory cannot afford that time on a production line.

Automotive Ethernet at 100 megabits per second, and increasingly at 1 gigabit per second over a single twisted pair, moves the same image in well under a minute even after protocol overhead and the target's own flash write time are accounted for. Flash writing, not transport, becomes the limiting factor, which is the correct place for the bottleneck to sit. Software images have grown in exactly the way that forces this change: an engine controller of the 1990s held tens of kilobytes, while a modern driver-assistance or infotainment controller holds hundreds of megabytes of code, maps, and neural network parameters. DoIP exists because the transport had to grow by three orders of magnitude to keep pace, and because the same Ethernet backbone was being installed for camera and sensor data regardless.

ODX and the Data-Driven Tester

A tester that has mastered UDS and ISO-TP still cannot diagnose anything. It knows how to ask for data identifier 0x1234 and how to receive four bytes back, but not that this control unit supports that identifier, that the first two bytes are an intake air temperature in tenths of a degree Celsius with an offset, or that the third byte is an enumeration in which the value five means "sensor circuit open." Historically this knowledge was compiled into tool software, one program per manufacturer per model year, which made every tool a maintenance liability and made independent tool coverage a matter of reverse engineering.

ODX, the Open Diagnostic Data Exchange format, replaces that with a machine-readable description. It is standardized as ISO 22901-1, published in 2008, and maintained by ASAM as ASAM MCD-2 D; ASAM lists version 2.2.0, released on 18 May 2008, and the format uses XML for interchange with the underlying data model expressed in UML. Files carry the extension .odx, and a complete deliverable is normally shipped as a .pdx package, a container holding all the files that describe a vehicle or a control unit together.

An ODX description states what a control unit can do and how to interpret it. It enumerates the supported diagnostic services with their exact request and response byte layouts. It defines data object properties, which are the conversion rules that turn raw bytes into physical quantities: linear scaling with factor and offset, text tables mapping numeric codes to strings, bit fields, and units. It lists the supported data identifiers, the fault codes with their text descriptions and the composition of their snapshot and extended data records, the routines and their parameters, and the communication parameters that a tester needs, including bit rates, addressing format, block size, separation time, and the timing values discussed earlier.

Crucially, ODX is layered to match how vehicles are actually built. A protocol layer describes what is common to a whole network. A base variant describes what is common to a family of control units, and an ECU variant describes one specific version, inheriting from the base and overriding only the differences. A variant identification procedure tells the tester how to determine, by reading identification data from the module in front of it, which variant description applies. Functional groups describe operations that span several control units. Separate categories describe flash data, ECU configuration, and vehicle-level information. The inheritance model matters because a manufacturer may ship a hundred variants of one control unit across markets and model years, and describing each from scratch would be unmanageable.

Around ODX sits a runtime standard. ISO 22900, the Modular Vehicle Communication Interface series, defines a hardware requirements part, a D-PDU API in part 2 that abstracts the physical communication interface so that any compliant vehicle communication interface works with any compliant software, and a diagnostic server API in part 3, also known as ASAM MCD-3 D, that exposes ODX-driven diagnostic operations to an application. In North America, SAE J2534 fills a related role for pass-through reprogramming and is the interface manufacturers are required to support so that independent repair facilities can reprogram emissions-related control units with their own hardware.

The argument for a data-driven tester over a hand-coded one is straightforward once the scale is clear. A manufacturer with a dozen model lines, each with several powertrains and several markets, and each control unit revised annually, faces thousands of distinct diagnostic descriptions. A hand-coded tool requires a software release for every one of those changes, with the testing and distribution burden that implies. A data-driven tool ships one runtime and loads a new .pdx package, which can be validated automatically against the standard's schema, delivered without a software release, and reused by every consumer at once. The same package drives the end-of-line tester in the plant, the dealer workshop tool, the roadside service tablet, the hardware-in-the-loop rig in the validation lab, and the back-end system that plans an over-the-air campaign. A supplier delivers the ODX description alongside the control unit as a contractual deliverable, so the description is authored once by the party that actually knows the software. Consistency follows from the architecture rather than from discipline.

OTX and Executable Test Sequences

ODX describes capability but not procedure. It states that a control unit supports a particular routine; it does not state that diagnosing a rough idle means reading four specific values, comparing them against limits, running one routine if the comparison fails and a different one if it passes, and instructing the technician to inspect a connector in between. That procedural knowledge traditionally lived in workshop manuals as prose, which meant it was executed by a human, inconsistently, and could not be reused by an automated system.

OTX, the Open Test sequence eXchange format, standardized as ISO 13209, makes procedures executable. Part 1 covers general information and use cases, part 2 specifies the core data model, part 3 specifies standard extensions, and part 4 defines an interface for expanded extensions. The core is a general-purpose programming model expressed in XML: procedures with typed parameters and return values, activities that perform steps, control flow with branches and loops, structured exception handling, and variable scoping. It is a programming language whose source form is designed for tools to generate and consume rather than for humans to type.

The extensions are what make it automotive. A diagnostic communication extension issues requests through an ODX-driven diagnostic server, so an OTX step can say "execute the service named ReadEngineTemperature on the engine control unit" and let the ODX data supply the byte layout. A human-machine interface extension displays instructions and collects technician input, which is how a guided procedure interleaves automated measurement with manual inspection. Further extensions handle internationalization so that one procedure serves every market, physical quantities and units, measurement device control, flash programming, and invocation of external jobs.

The practical uses are three. Guided fault-finding turns a workshop manual chapter into a sequence the tool executes with the technician, which raises the floor of diagnostic quality across a service network of widely varying skill. End-of-line test sequences in the factory are authored in the same language, so a procedure validated during development can be reused in production and in the field rather than reimplemented three times. Service campaigns and recalls are distributed as sequences: the manufacturer publishes a procedure that checks whether a given vehicle is affected, performs the remedy, and records the result, and every workshop executes exactly the same steps. Because an OTX document is text, it can be version-controlled, reviewed, and diffed like any other engineering artifact, which matters when a procedure touches a safety-related system and must be auditable years later.

Gateways, Filtering, and the Security of a Service That Writes Memory

Every protocol described so far assumes a tester that is entitled to be there. The vehicle cannot assume that, and the architecture that enforces the distinction is the gateway.

The Gateway as Router and Filter

A modern vehicle does not connect its diagnostic connector directly to the buses that carry braking and steering messages. A central gateway sits between them, and in newer designs a small number of domain or zone controllers sit between the gateway and the individual modules. The gateway routes diagnostic traffic, translating between the transport used on the external interface and the transport used internally, and holding the address table that maps a logical address to a bus and a node.

Because every diagnostic message passes through it, the gateway is also the natural filter. It can restrict which services are forwarded to which targets, so that a request to write memory reaches a module only when the vehicle is stationary and the tester has been authenticated, while a request to read a fault code passes freely. It can rate-limit traffic from the diagnostic connector so that a flood cannot starve safety-related messages of bus bandwidth. It can refuse to route any diagnostic request to a chassis controller while the vehicle is in motion. SAE J3138 sets out recommended practice for securing the diagnostic link connector along these lines, distinguishing the read-only access that must remain open for legislated and aftermarket purposes from the intrusive access that must not be available to an arbitrary device plugged in under the dashboard.

This is not a theoretical concern. In 2015, the researchers Charlie Miller and Chris Valasek demonstrated remote control of a Jeep Cherokee by reaching the head unit over the cellular network, reprogramming a microcontroller that bridged to the vehicle's CAN buses, and then injecting messages that operated the vehicle's controls. Fiat Chrysler recalled approximately 1.4 million vehicles in response. The lesson drawn across the industry was that a reprogrammable bridge between an internet-connected component and a safety-related bus is the whole attack, and that the gateway must be a real security boundary rather than a routing convenience.

Authenticated Diagnostics

Regulation has since made this explicit. UN Regulation No. 155 requires a certified cybersecurity management system covering a vehicle type across its lifecycle, and UN Regulation No. 156 requires an equivalent software update management system, including the integrity and authenticity of updates. ISO/SAE 21434 supplies the engineering process for road vehicle cybersecurity that manufacturers use to demonstrate conformity. Together they turn diagnostic security from an internal preference into a type-approval condition in the markets that apply the United Nations vehicle regulations.

The technical response has several strands. The Authentication service, identifier 0x29, replaces shared-secret seed-and-key with certificate-based proof of identity and role-based authorization. Secure boot ensures that a module executes only software whose signature it can verify, so that even a successful download of a hostile image does not produce a running hostile module. Secure onboard communication authenticates the routine messages between control units, so that injected frames are rejected even when an attacker reaches the bus. Hardware security modules embedded in the microcontroller hold the keys and perform the cryptography, so that key material never appears in ordinary flash. Backend systems govern which tools hold valid certificates and revoke them when a tool is lost or a workshop loses its authorization.

Access, the Aftermarket, and Right to Repair

Every one of those defenses also raises a barrier to legitimate independent repair, and the resulting tension is unresolved. A vehicle that will accept a software update only from a certificate-holding tool is a vehicle whose manufacturer decides who may repair it. Regulators have responded from the other direction: emissions law in the United States requires manufacturers to make emissions-related reprogramming available to independent facilities through SAE J2534 pass-through hardware, and Massachusetts voters approved a ballot measure in 2020 requiring an open, standardized telematics platform for vehicles sold in the state. European motor vehicle block exemption rules similarly require access to technical repair information on non-discriminatory terms.

The likely resolution is not less security but a managed identity infrastructure, in which an independent technician holds a credential issued through an accreditation scheme rather than no credential at all, and in which the vehicle enforces authorization by role rather than by brand. That is precisely what certificate-based authentication makes possible, since it can distinguish a tool permitted to read fault memory from one permitted to reprogram a braking controller without requiring the two to share a secret. Whether the schemes that issue those credentials will be genuinely open is a policy question rather than a protocol question, but the protocols now under deployment are, at least, capable of expressing the distinction.

Conclusion

The vehicle diagnostic stack is a layered design whose separations do real work. ISO 14229 defines what a request means without reference to any bus, which is why the same diagnostic application survives a platform migration from CAN to Ethernet. ISO 15765-2 and ISO 13400 define how a request travels, each optimized for the medium beneath it. ODX describes what a specific control unit supports and how to interpret its bytes, which is what allows one tester program to serve thousands of vehicle configurations. OTX describes what to do with all of it, turning a workshop manual into an executable and auditable procedure.

The services themselves reward study because they are used far outside the repair bay. Session control and tester present define the state machine that every other operation lives inside. Security access and its successor, certificate-based authentication, decide who may change a vehicle. ReadDTCInformation, with its status bits, snapshots, and extended data, holds the evidence that separates a present fault from an intermittent one. Input/output control and routine control make the vehicle act on command. Request-download and transfer-data make software update an ordinary diagnostic operation, which is the design decision that put over-the-air updates within reach and simultaneously created the industry's most sensitive interface.

Practitioners should take two habits from this material. The first is to locate a problem in the right layer before attacking it: silence on the bus is a transport or addressing question, a negative response code is an application-layer answer that already names its own cause, and a correct exchange that displays nonsense is a description-data question. The second is to prefer data-driven and sequence-driven tooling over hand-coded equivalents, because a vehicle range changes faster than software releases can follow. As vehicles consolidate onto fewer, more powerful controllers connected by Ethernet, the transport underneath will keep changing and the service semantics above it will largely stay put, which is exactly the outcome the layering was designed to produce.

Related Topics