Besides the hardware investigation, I continued the Google research.
- The CAN bus matrix and Lin Description Files (next LDF) were found: https://openinverter.org/forum/viewtopic.php?t=3152
- The VAG BAP discover was to found at all unless the article in the web archive history: https://web.archive.org/web/20241005094756/https://blog.dietmann.org/?p=324
- Another document with the name 476121999-BAP-FC-NAV-SD-P30DF48-v2-80-F-pdf was found.
It also sheds some light on the communication protocol. The UGDO_B is the HomeLink buttons. The UGDOe is the HomeLink module. Based on this, half of the shade was eliminated, and information about the buttons' communication was discovered. The BCM drives the LIN bus, it sends the *e_ messages to request information and the *s_ headers to receive the response. The details of the hardware level can be found here: https://www.csselectronics.com/pages/lin-bus-protocol-intro-basics.
UGDO_Be_01: 4, BCM1, 6 {
UGDO_SW_LED_Code, 0 ;
UGDO_SW_Function, 5 ;
DI_KL_58xs, 8 ;
}
UGDO_Bs_01: 3, UGDO_B, 6 {
UGDO_SW_Buttons, 0 ;
UGDO_SW_Switchboard, 4 ;
UGDO_B_ResponseError, 16 ;
}
UGDOe_02: 46, BCM1, 6 {
UGDO_Buttons, 0 ;
Klemme_15, 6 ;
ZV_auf_Funk, 7 ;
ESP_v_Signal_8Bit, 8 ;
UGDO_Switchboard, 16 ;
SM_Parken_UGDO_Anf, 24 ;
SM_Parken_UGDO_Aktion, 28 ;
}
UGDOe_BAP: 31, BCM1, 8 {
BAPe_LSG_ID1, 0 ;
BAPe_Opcode, 4 ;
BAPe_Segment, 7 ;
BAPe_FCT_ID, 8 ;
BAPe_LSG_ID2, 14 ;
BAPe_Data_Byte_1, 16 ;
BAPe_Data_Byte_2, 24 ;
BAPe_Data_Byte_3, 32 ;
BAPe_Data_Byte_4, 40 ;
BAPe_Data_Byte_5, 48 ;
BAPe_Data_Byte_6, 56 ;
}
UGDOs_02: 47, UGDO_S, 8 {
UGDO_LED_Code_01, 0 ;
UGDO_Function_01, 5 ;
UGDO_Failure_Antenne, 8 ;
UGDO_Failure_Codierung, 9 ;
UGDO_Failure_Hardware, 10 ;
UGDO_ResponseError, 16 ;
UGDO_Channel_1, 24 ;
UGDO_Channel_2, 25 ;
UGDO_Channel_3, 26 ;
UGDO_Channel_4, 27 ;
UGDO_Channel_5, 28 ;
UGDO_Channel_6, 29 ;
UGDO_Channel_7, 30 ;
UGDO_Channel_8, 31 ;
UGDO_Channel_9, 32 ;
UGDO_Channel_10, 33 ;
UGDO_Channel_11, 34 ;
UGDO_Channel_12, 35 ;
UGDO_Channel_13, 36 ;
UGDO_Channel_14, 37 ;
UGDO_Channel_15, 38 ;
UGDO_DoorState, 40 ;
}
UGDOs_BAP: 32, UGDO_S, 8 {
BAPs_LSG_ID1, 0 ;
BAPs_Opcode, 4 ;
BAPs_Segment, 7 ;
BAPs_FCT_ID, 8 ;
BAPs_LSG_ID2, 14 ;
BAPs_Data_Byte_1, 16 ;
BAPs_Data_Byte_2, 24 ;
BAPs_Data_Byte_3, 32 ;
BAPs_Data_Byte_4, 40 ;
BAPs_Data_Byte_5, 48 ;
BAPs_Data_Byte_6, 56 ;
}
Also, this file has a bit of info about the diagnosis frames used to work with ODIS. But unfortunately the amount of info was a bit.
Diagnostic_frames {
MasterReq: 0x3c {
MasterReqB0, 0 ;
MasterReqB1, 8 ;
MasterReqB2, 16 ;
MasterReqB3, 24 ;
MasterReqB4, 32 ;
MasterReqB5, 40 ;
MasterReqB6, 48 ;
MasterReqB7, 56 ;
}
SlaveResp: 0x3d {
SlaveRespB0, 0 ;
SlaveRespB1, 8 ;
SlaveRespB2, 16 ;
SlaveRespB3, 24 ;
SlaveRespB4, 32 ;
SlaveRespB5, 40 ;
SlaveRespB6, 48 ;
SlaveRespB7, 56 ;
}
}
After capturing the LIN messages during the ODIS block identification procedure, I got a list of frames. It will be attached as a file. In that mess of frames, I was able to see the interesting frames that looked pretty known.
- 0x3C0103226004FFFFFF75
- 0x3D01066260042500000D
What if we change the coding? And here we go:
- 0x3C01062E600421000041
- 0x3D01036E6004FFFFFF29
Let's make the messages clearer. Based on the LDF, we can get the info about the bus. It is the LIN 2.0 version and works at 19.2 kbps.
...
LIN_description_file;
LIN_protocol_version = "2.0";
LIN_language_version = "2.0";
LIN_speed = 19.2 kbps;
...
Also, based on the specification of the LIN, the first byte is the header, and the last one is the checksum. To get the checksum, https://linchecksumcalculator.machsystems.cz/ can be used.

And it looks true. 0x 3C01062E600421000041, the frame ID matches with the LFD, and the checksum is the same. So, now the message looked less terrible. After sniffing a few more messages, they became more and more logical but still not clear.
0x3C0C03226205FFFFFF67 0x3D0C100E626205344D8A 0x3D0C2130393539373192 0x3D0C22394120FFFFFF37 0x3C0C03226C05FFFFFF5D 0x3D0C1010626C05475464 0x3D0C214F20424620209A 0x3D0C222020202020FF31 0x3C0C03226605FFFFFF63 0x3D0C100E626605344D86 0x3D0C2130393539373192 0x3D0C22394120FFFFFF37 0x3C0C03226405FFFFFF65 0x3D0C10076264053030B0 0x3D0C213130FFFFFFFF71 0x3C0C03226805FFFFFF61 0x3D0C0662680548303174 0x3C0C03226A05FFFFFF5F 0x3D0C1017626A05323098 0x3D0C213137303232389D 0x3D0C223132343435319F 0x3D0C23203030363031B8 0x3C0C03226005FFFFFF69 0x3D0C037F2231FFFFFF1E 0x3C0C03226E05FFFFFF5B 0x3D0C101A626E0554524D 0x3D0C21572D59534A3225 0x3D0C22382E30322E31A9 0x3D0C23373030303130A7 0x3D0C24363031FFFFFF38 0x3C0103226204FFFFFF73 0x3D01100E626204344D96 0x3D0121303930373431A7 0x3D0122304120FFFFFF4B 0x3C0103226C04FFFFFF69 0x3D011010626C04555363 0x3D0121484C35202020B3 0x3D01222020202020FF3C 0x3C0103226604FFFFFF6F 0x3D01100E626604344D92 0x3D0121303930373431A7 0x3D0122304120FFFFFF4B 0x3C0103226404FFFFFF71 0x3D0110076264043030BC 0x3D01213530FFFFFFFF78 0x3C0103226804FFFFFF6D 0x3D01066268044830347D 0x3C0103226A04FFFFFF6B 0x3D011017626A043030A6 0x3D0121303030303936AD 0x3D012230303333355A86 0x3D012333434935303284 0x3C0103226004FFFFFF75 0x3D01066260042500000D 0x3C0103226E04FFFFFF67 0x3D01101A626E04475860 0x3D0121312D475831317D 0x3D0122332E30332E31B8 0x3D0123373030303133AF 0x3D0124434935FFFFFF19
The list has a strict repeat, and its first part almost always was 0x3C0C0322 and 0x3C010322. As the VAG use UDS for diagnostic i decide to compare the messages with the UDS messages structure. Details here: https://www.csselectronics.com/pages/uds-protocol-tutorial-unified-diagnostic-services. After exposing the capture by the UDS message structure, it starts looks next:
ID PCI SID SubFunction DataID Empty Checksum 0x3C 0C 03 22 6205 FFFFFF 67 0x3C 0C 03 22 6C05 FFFFFF 5D 0x3C 01 03 22 6204 FFFFFF 73 0x3C 01 03 22 6C04 FFFFFF 69
But this structure was described for the CAN bus, and the PCI (Protocol Contriol Info) should not change its value. Unless for requesting simple data. Thankfully, the ODIS provides the possibility to force read the identification of the block. And after doing it just for the buttons, I got the next sniff:
0x3C0C03226205FFFFFF67 0x3D0C100E626205344D8A 0x3D0C2130393539373192 0x3D0C22394120FFFFFF37 0x3C0C03226C05FFFFFF5D 0x3D0C1010626C05475464 0x3D0C214F20424620209A 0x3D0C222020202020FF31 0x3C0C03226605FFFFFF63 0x3D0C100E626605344D86 0x3D0C2130393539373192 0x3D0C22394120FFFFFF37 0x3C0C03226405FFFFFF65 0x3D0C10076264053030B0 0x3D0C213130FFFFFFFF71 0x3C0C03226805FFFFFF61 0x3D0C0662680548303174 0x3C0C03226A05FFFFFF5F 0x3D0C1017626A05323098 0x3D0C213137303232389D 0x3D0C223132343435319F 0x3D0C23203030363031B8 0x3C0C03226005FFFFFF69 0x3D0C037F2231FFFFFF1E 0x3C0C03226E05FFFFFF5B 0x3D0C101A626E0554524D 0x3D0C21572D59534A3225 0x3D0C22382E30322E31A9 0x3D0C23373030303130A7 0x3D0C24363031FFFFFF38
This was interesting because the LDF has the next data:
UGDO_B{
LIN_protocol = "2.0" ;
configured_NAD = 0xC ;
product_id = 0x0, 0x0, 0 ;
response_error = UGDO_B_ResponseError ;
P2_min = 10 ms ;
ST_min = 10 ms ;
configurable_frames {
UGDO_Be_01 = 0x2004 ;
UGDO_Bs_01 = 0x2003 ;
ISPe_01 = 0x0 ;
TCHe_01 = 0x0 ;
}
}
UGDO_S{
LIN_protocol = "2.0" ;
configured_NAD = 0x1 ;
product_id = 0x0, 0x0, 0 ;
response_error = UGDO_ResponseError ;
P2_min = 10 ms ;
ST_min = 10 ms ;
configurable_frames {
UGDOe_02 = 0x112E ;
UGDOe_BAP = 0x111F ;
UGDOs_02 = 0x112F ;
UGDOs_BAP = 0x1120 ;
ISPe_01 = 0x0 ;
LIMe_02 = 0x0 ;
}
}
So, looks like the first byte of data of the LIN frame is not a PCI but the NAD (Node Address).
ID NAD PCI SID SubFunction DataID Empty Checksum 0x3C 0C 03 22 62 05FF FFFF 67 0x3C 0C 03 22 6C 05FF FFFF 5D 0x3C 01 03 22 62 04FF FFFF 73 0x3C 01 03 22 6C 04FF FFFF 69
And here we get four columns looking true. But no info about the SubFunction and Data ID. And here, the ODIS will help a bit. After running the measurement from ODIS. A part of the report is attached.

The LIN frames were the next:
0x3C0103223AF7FFFFFFA7 0x3D0104623AF700FFFF66 0x3C0103223AFFFFFFFF9F 0x3D0105623AFF0477FFE1 0x3C010322500CFFFFFF7D 0x3D010462500C05FFFF37 0x3C0103223AE5FFFFFFB9 0x3D01100A623AE5000062 0x3D01210000000000FFDD 0x3C0103223AE6FFFFFFB8 0x3D01100A623AE6000061 0x3D01210000000000FFDD 0x3C0103223AE7FFFFFFB7 0x3D01100A623AE7000060 0x3D01210000000000FFDD 0x3C0103223AE8FFFFFFB6 0x3D01037F2278FFFFFFE1 0x3D011008623AE8000061 0x3D0121000000FFFFFFDD 0x3C0103223AE9FFFFFFB5 0x3D01037F2278FFFFFFE1 0x3D011008623AE9000060 0x3D0121000000FFFFFFDD
Still a mess? - For sure. But what if we divide the bytes based on our knowledge? Now it looks not so weird?

B0 is always 0x22, 0x62, and 0x7F. Let's check the UDS. And looks like they are a SID request (0x22) and SID response (0x62) for Read Data by Identifier. What about the 0x7F? Of course, it looks like the SID negative response.
What if we split B1 and B2 together? Looks familiar? Take a look at the ODIS report. It is data ID for sure. Based on discovery, the LIN bus has no SubFunction ID; at least, it looks so. So, now we can put the information together. And even decode a bit.

Stepan Skopivskiy
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.