Close

UGDO BAP

A project log for Opensource HomeLink ecu for VAG

Open-source HomeLink module for VAG cars. Replaces the stock unit, working with standard LIN Bus and supporting various garage doors.

stepan-skopivskiyStepan Skopivskiy 03/23/2025 at 10:550 Comments

Besides successfully discovering the communication between the hardware buttons, another problem remained — there was absolutely nothing about the UGDO (universal garage door opener) BAP (German: “Bedien- und Anzeigeprotokoll” ~ control- and display protocol).

The only valuable paper I found was this one (from a web archive): https://web.archive.org/web/20241005094756/https://blog.dietmann.org/?p=324. I saved a copy in PDF format just in case. But even it did not have any mentions about the UGDO. Another interesting document I found was https://www.scribd.com/document/476121999/BAP-FC-NAV-SD-P30DF48-v2-80-F-pdf. It has also been saved as a pdf just for easy access. It describes how the other component (Navigation) communicates using BAP. Unfortunately, also it has a lot of references to other internal documents.

Another way was to start from the MMI. But here is just a bit of information too. The only mention of software of the MMI I found was this repository - https://github.com/grajen3/mib2-lsd-patching. It has a lot of mentions about the UGDO but as the code is just a decompiled Java classes there are a lot of missed constants too. The one of files is - https://github.com/grajen3/mib2-lsd-patching/blob/aa-in-vc/lsd_java/org/dsi/ifc/carcomfort/UGDOButtonListRA0.java. And the other files are on the screenshot.

But as there are no constant values it was not so valuable, at least for now. The last way left was sniffing. The MMI uses the CAN to communicate with the BCM (through the gateway), and then the BCM communicates to UGDO by LIN. So, instead of sniffing the LIN the CAN was chosen. Also, the DBC (CAN messages matrix) file helps to filter the necessary messages. Sniffing can be done with the cheap module - https://canable.io/.

The first session was pretty useless. I start recording the CAN messages and start doing some actions like program, rename, delete buttons, etc. The result - just a mess of data and actions. Before the second session, an "action" plan was prepared.

And now it is a valuable dataset. Using the BAP CAN message description mentioned at the log start, some data preparation was done. The screenshot shows the part of messages after the ignition turns on.

It shows the initialization of the BAP, FCT_ID: 0x02 and 0x01. The information about those function IDs was found in both sources: the BAP description blog and the NAV_SD_Bap document. And it looks like the common structure for any BAP member. Then, the specific function id goes - 0x10, with a long amount of data and some interesting repeating in it. Using the same doc, the collapsed data is the next:

0x1B084000030112D093D0B0D1803120D09AD0BED180D0B5D18948DDF80240A96E011001010200F0000000F00000000002000300F0000000F0000000000300

So long data can be only in an array. Thankfully in the NAV_SD doc file, there is general information about the array formats, they are the same between the different functions.

Based on found in Google information, BAP has four kinds of functions: property, method, array, and cache. Each of them has its own sets of op_codes.

Opcode

value

Function class

Property

Function class

Array

Function class

Method

Function class

Cache

Direction

0x0

Set

SetArray

Start

ASG -> FSG

Reset

FSG -> ASG

0x1

Get

GetArray

Abort

GetAll

ASG -> FSG

0x2

SetGet

SetGetArray

StartResult

ASG -> FSG

0x3

HeartbeatStatus

ChangeArray

Processing

FSG -> ASG

0x4

Status

StatusArray

Result

StatusAll

FSG -> ASG

0x5

StatusAck

FSG -> ASG

0x6

Ack

ASG -> FSG

0x7

Error

Error

Error

Error

FSG -> ASG

Based on the information, the sequence is the next: after turning on the ignition, the MMI requests the information and waits for the array from the module. Skipping the BAP message header etc, the clear request-response data is the next:

0x1B000003
0x1B084000030112D093D0B0D1803120D09AD0BED180D0B5D18948DDF80240A96E011001010200F0000000F00000000002000300F0000000F0000000000300

The get array op_code has the next format: ASG_IDTAIDArrayHeader. The ASG_ID (Identifies the requesting) and TAID (Identifies the transaction (pair of GetArray and StatusArray). The transaction ID (TAID) is unique in combination with the parameter ASG_ID) are the components of one byte.

The ArrayHeader also is the combination of parameters: Mode (4bit), RecordAddress (4bit), Start Number (1 byte), and Elements (1 byte).

And now, the request can be explained: 0x1B000003.

The same for the response. The common response is the combination of the next data: ASG_ID, TAID, TotalNumListElements, ArrayHeader, and Data. So, the parsed response is the next:

Based on the Mode, (0x4) it means that the response elements have their position in response. So, the rest of the data looks like has an index, based on the total elements number is a byte, the position of each element also should use the byte for itself.

0112D093D0B0D1803120D09AD0BED180D0B5D18948DDF80240A96E011001010200F0000000F00000000002000300F0000000F0000000000300

 Also, we have another pair of request-response:

0x1C100303
0x1C085003030400F0000000F00000000004000500F0000000F00000000005000600F0000000F0000000000600
0x1D100603
0x1D085006020700F0000000F00000000007000800F0000000F0000000000800

Based on already known data, it is 3 pairs to request the 8 elements in total, split by 3 elements in each response (2 in last). The first response has 3 elements and definitely some data. The second and third are definitely empty. So, if extract the header (ASG_ID, TAID, TotalNum, and ArrayHeader) the clear data converts to:

0400F0000000F00000000004000500F0000000F00000000005000600F0000000F0000000000600
0700F0000000F00000000007000800F0000000F0000000000800

And now, knowing the number of elements in each, the data can be splitted into the next list:

And even the the first set:

The first byte of each element is the position of the element. Based on Mode. The next is the data of the element. Unfortunately unknown yet.

Discussions