VW Transport Protocol 2.0 (TP 2.0)
While most diagnostic protocols on CAN use ISO-TP to transfer payloads larger than 8 bytes, Volkswagen uses a custom protocol on older models. This protocol is called VW Transport Protocol 2.0 (TP 2.0). It's usually used to transfer KWP2000 diagnostic messages, but can also be used to transfer other data.
TP 2.0 uses the concept of channels to communicate data between the tester and the ECU. Once a channel is opened, data can be exchanged. There is no official specification of TP 2.0, so the protocol description here is based on reverse engineering work by Jared Wiltshire.
VW TP 2.0 uses four types of packets: channel setup, channel parameters, data packets, and broadcast.
Channel Setup
The first step in opening a channel is sending a channel setup request message. It's sent on Arbitration ID 0x200, and the response will be sent on 0x200 + logical address of the ECU. For example, the engine control unit has a logical address of 0x01, so the response will be on 0x201.
The channel setup message is 7 bytes long. Each of the RX and TX IDs is split across two bytes: a low byte holding the lower 8 bits of the 11-bit CAN ID, and a "validity + prefix" byte where the high nibble is the validity flag (0x0 = valid, 0x1 = invalid) and the low nibble is the upper nibble of the CAN ID. Read together as a little-endian 16-bit value, this gives V·ID with V in the top nibble.
Opcode
0xC0— Setup Request0xD0— Positive Response0xD6–0xD8— Negative Response
Example
In the example below the tester opens a channel to the ECU with logical address 0x09. The RX ID is set to invalid to let the ECU decide where it listens. The TX ID is set to 0x300 to request that the ECU transmit on 0x300. The ECU responds with a positive response, acknowledges that it will listen on 0x300, and tells the tester to send to 0x7A8.
Channel setup
| Field | Mnemonic | Value | Description |
|---|---|---|---|
| Destination | Dest | 09 | Logical address of the ECU. 0x09 here. |
| Opcode | Op | C0 | 0xC0 = Setup Request. |
| RX ID low byte | RX | 00 | Low 8 bits of the RX ID (CAN ID the ECU should listen on). |
| RX V & prefix | RXVP | 10 |
|
| TX ID low byte | TX | 00 | Low 8 bits of the TX ID (CAN ID the ECU should transmit on). |
| TX V & prefix | TXVP | 03 |
|
| Application | App | 01 | Always 0x01 for KWP2000. |
| Field | Mnemonic | Value | Description |
|---|---|---|---|
| Destination | Dest | 00 | Logical address of the tester (always 0x00). |
| Opcode | Op | D0 | 0xD0 = Positive Response. 0xD6–0xD8 indicate a negative response. |
| RX ID low byte | RX | 00 | ECU confirms it will listen on this CAN ID. |
| RX V & prefix | RXVP | 03 |
|
| TX ID low byte | TX | A8 | Tester should send to this CAN ID. |
| TX V & prefix | TXVP | 07 |
|
| Application | App | 01 | Echoed. |
Channel Parameters
After opening the channel, some timing parameters need to be negotiated. The tester sends a parameters request message, and the ECU responds with a parameters response message. The parameters are used to determine the timing of the channel.
Opcode
0xA0— Parameters request (6 bytes)0xA1— Parameters response (6 bytes)0xA3— Channel test (1 byte). The ECU responds with an0xA1message. Used to keep the channel alive.0xA4— Break (1 byte). The receiver discards all data since last ACK.0xA8— Disconnect (1 byte). Closes the channel. Receiver responds with a disconnect.
Timing Parameters
T1, T2, T3, T4 are each one byte. Bits 7–6 encode the time units and bits 5–0 encode a multiplier. The unit values are:
0x0— 0.1 ms0x1— 1 ms0x2— 10 ms0x3— 100 ms
The total time is units × multiplier. For example 0x8A = 10 001010 = 10 ms × 10 = 100 ms.
Example
Example of the tester exchanging the timing parameters. Recall the ECU listens on 0x7A8 and will transmit on 0x300. The tester requests a block size of 15, T1 of 100 ms, and T3 of 1 ms. The ECU responds with a block size of 15, T1 of 100 ms, and T3 of 10 ms.
Channel parameters
| Field | Mnemonic | Value | Description |
|---|---|---|---|
| Opcode | Op | A0 | 0xA0 = Parameters request. |
| BlockSize | BS | 0F | 15 packets between ACKs. |
| T1 | T1 | 8A |
|
| T2 | T2 | FF | Always 0xFF (unused). |
| T3 | T3 | 0A |
|
| T4 | T4 | FF | Always 0xFF (unused). |
| Field | Mnemonic | Value | Description |
|---|---|---|---|
| Opcode | Op | A1 | 0xA1 = Parameters response. |
| BlockSize | BS | 0F | ECU agrees to 15 packets per block. |
| T1 | T1 | 8A | 100 ms (same encoding as request). |
| T2 | T2 | FF | Always 0xFF. |
| T3 | T3 | 4A |
|
| T4 | T4 | FF | Always 0xFF. |
Data Transmission
After opening a channel, data can be transmitted. Up to 7 bytes of payload can be sent at a time. During channel setup, a block size was negotiated; after this many data transmission packets, an ACK is required. The first nibble of the first byte contains the opcode, and the second is used as a counter. Note that this counter behaves in a counterintuitive way: both tester and ECU have their own counter that persists between transmissions. The counter is incremented after each data transmission. An ACK does not increment any counter, but is expected to use the counter value of the last data transmission that is being acknowledged plus one.
Opcode
0x0— Waiting for ACK, more packets follow (max block size reached)0x1— Waiting for ACK, last packet0x2— Not waiting for ACK, more packets to follow0x3— Not waiting for ACK, last packet0xB— ACK, ready for more data0x9— ACK, not ready for more data
| Field | Mnemonic | Value | Description |
|---|---|---|---|
| Op & Sequence | Op|Seq | 12 |
|
| Length | Len | 00 02 | Big-endian total payload length (2 bytes). Only present in the first frame of a message. |
| Payload | Data | 1A 9B | KWP2000 service ID (0x1A read ECU identification) and parameter (0x9B). |
| Field | Mnemonic | Value | Description |
|---|---|---|---|
| Op & Sequence | Op|Seq | B3 |
|
Example
In this example the tester has some KWP2000 communication with the ECU. There are some short packets to enter a diagnostics mode, then a larger payload is requested using service 0x1A (Read ECU Identification) to get the firmware version.
- Tester
0x7A81000021089Payload 10 89 — enter diag mode 0x89 - ECU
0x300B1ACK - ECU
0x3001000025089Payload 50 89 — mode 0x89 entered - Tester
0x7A8B1ACK - Tester
0x7A81100021089Payload 10 89 — enter diag mode 0x89 - ECU
0x300B2ACK - ECU
0x3001100025089Payload 50 89 — mode 0x89 entered - Tester
0x7A8B2ACK - Tester
0x7A81200021A9BPayload 1A 9B — Read ECU Identification - ECU
0x300B3ACK - ECU
0x3002200305A9B314B30Payload "Z.1K0" - ECU
0x3002339303931343445Payload "909144E" - ECU
0x3002420203235303100Payload " 2501." - ECU
0x3002500000000064016Payload ".....@." - ECU
0x30026054D4550535F5APayload ".MEPS_Z" - ECU
0x30027464C53204B6C2EPayload "FLS Kl." - ECU
0x3002820313834202020Payload " 184. " - ECU
0x3001920Payload " " - Tester
0x7A8BAACK
Broadcast
For diagnostics requests, it might be useful to quickly send a message without needing a (long) response, and without needing to open a channel first. The broadcast packets have no form of ACK, so they are sent 5 times.
Opcode
0x23— Broadcast request0x24— Broadcast response
| Field | Mnemonic | Value | Description |
|---|---|---|---|
| Destination | Dest | 01 | Logical address of the destination module. |
| Opcode | Op | 23 | 0x23 = Broadcast request, 0x24 = Broadcast response. |
| KWP2000 data | Data | 4 KWP2000 bytes | Service ID and parameters. |
| Response flag | Resp | 00 | 0x00 = response expected. 0x55 or 0xAA = no response expected. |