After getting the list of elements (BAP Array) the structure of the item data is still unknown. During the testing of the actions and messages, a few actions were recorded. The next data is the pairs of ASG and FSG (request and response).
- Create a new button on position 2:
0x15020201 0x15080202110201
- Create a new button on position 7:
0x17020701 0x17080207012000
Create a new button in D-mode:
0x184505010560 0x98084505010560
Create a new button in UR-mode:
0x1A4506010650 0x9A084506010650
Rename the 2nd button to "Гар. 22222":
0x1C440201020DD093D0B0D1802E203232323232 0x9C08440201020DD093D0B0D1802E203232323232
Rename the 7th button to "7777777777":
0x1D440701070A37373737373737373737 0x9D08440701070A37373737373737373737
Save position:
0x1C4102010228DEF80256A76E011001 0x9C084102010228DEF80256A76E011001
All this req/res comes to and from function id - 0x10. So, looks like all "CRUD" operations are done through that function. Also, if to do the HEX to Text conversion some RAW data can be extracted.
After hours of "reading" the code, some details were discovered. For example, the classes from the found repository have a pretty same structure like the data in the CAN messages. Here the classes with their property members.
public class UGDOButtonListRA0 {
public int pos;
public String name;
public float positionLatitude;
public float positionLongitude;
public int learnedState;
public int hardkey;
public int softkey;
public UGDOSpecialFeatures specialFeatures;
}
public class UGDOButtonListRA1 {
public int pos;
public float positionLatitude;
public float positionLongitude;
public int learnedState;
public UGDOSpecialFeatures specialFeatures;
}
public class UGDOButtonListRA2 {
public int pos;
public int learnedState;
public UGDOSpecialFeatures specialFeatures;
}
public class UGDOButtonListRA3 {
public int pos;
public UGDOSpecialFeatures specialFeatures;
}
public class UGDOButtonListRA4 {
public int pos;
public String name;
}
public class UGDOButtonListRA5 {
public int pos;
public int learnedState;
}
And here, let's remember the array header structure: Mode (4bit), RecordAddress (4bit), Start Number (1 byte), and Elements (1 byte). Do You see some relations? What if convert RecordAddress to RA?
So, now, let's check rename and save position (both are requests from ASG):
0x1D440701070A37373737373737373737 0x1C4102010228DEF80256A76E011001
Based on the structure, the ASG_ID, TAID, ArrayHeader: Mode (4bit), RecordAddress (4bit), Start Number (1 byte), and Elements (1 byte). And now, the record address for rename is 4, and for set position 1. And now, let's check the Java class once again:
public class UGDOButtonListRA1 {
public int pos;
public float positionLatitude;
public float positionLongitude;
public int learnedState;
public UGDOSpecialFeatures specialFeatures;
}
public class UGDOButtonListRA4 {
public int pos;
public String name;
}
And it is a win! It has a logic now. MMI input has a limit for names - 10 chars max. Also, the known information is that the rename was to "7777777777" for the 7th button, and based on class, it is the only information in the data "package". Using this knowledge let's parse the whole message:
0x1D440701070A37373737373737373737
- 0x1 - ASG_ID
- 0xD - TAID
- 0x4 - Mode
- 0x4 - RecordAddress
- 0x07 Start Number
- 0x01 Elements
- And data
0x070A37373737373737373737
This is also pretty logical: char "7" in hex format is 0x37. So, the last 10 bytes is the "7". The first byte is the position, based on RA4 class. And, the last unrecognized byte is 0x0A. But what if you convert it to decimal? 0x0A = 10 (dec) Could it be the length of the string? It is! Because the parser should know how long the string is to know where the next data is starting (or ends current).
And what about the save position action class? Which is RA1. Doing the same will add some details here:
0x1C4102010228DEF80256A76E011001
- 0x1 - ASG_ID
- 0xD - TAID
- 0x4 - Mode
- 0x1 - RecordAddress
- 0x02 Start Number
- 0x01 Elements
- And data
0x0228DEF80256A76E011001
- 0x02 seems like the position. The RA1 also has: positionLatitude, positionLongitude, learnedState, and specialFeatures. The last three bytes looks definitely like a state and features configs. But three bytes instead of two is a bit of confusion. Assuming that the classes don't lie, we can define only two bytes for learned state, and special features. The position latitude, and longitude left on 0x28DEF80256A76E01, which can be easily divided by two:
- 0x28 DE F8 02
- 0x56 A7 6E 01
Converting 0x28DEF802 and 0x56A76E01 to the decimal does not have any logic.
0x28DEF802 = 685701122
0x56A76E01 = 1453813249
The actual position lon and lat was lat: 49.8641974062143, and lon: 24.02915713268198. And it is not that position definitely.
But we have the magic document regarding the NAV SD Bap. The only mentions about those coordinates are there:

We can see that these values should be decimals that have step 1E-06 (0,000001). So, let's convert our coordinates to that format and hex and add zero to have the same size as the sniffed data:
49.8641974062143 = 49864197 = 0x02 F8 DE 05
24.02915713268198 = 24029157 = 0x01 6E A7 E5
Looking similar? For sure! Let's compare them a bit closer:
| Parameter | Data from CAR | Data from Doc |
| latitude | 0x28 DE F8 02 | 0x02 F8 DE 05 |
| longitude | 0x56 A7 6E 01 | 0x01 6E A7 E5 |
Looking like the bytes in the car are reversed. After fixing them and converting based on step dimension they will have the next look:
0x28 DE F8 02 = 0x02 F8 DE 28 = 49.864232
0x56 A7 6E 01 = 0x01 6E A7 56 = 24.029014
Here we go! Now the most "loaded" data are parsed and understood. Based on this knowledge we can define that the data requested and received after turning on the ignition is the Record Address 0 or UGDOButtonListRA0.
public class UGDOButtonListRA0 {
public int pos;
public String name;
public float positionLatitude;
public float positionLongitude;
public int learnedState;
public int hardkey;
public int softkey;
public UGDOSpecialFeatures specialFeatures;
}
And it has that data (the hex string is the exact element, not the whole data package):
0x0112D093D0B0D1803120D09AD0BED180D0B5D18948DDF80240A96E01100101
- 0x01 - position
- 0x12 - string length (18 bytes)
- 0xD093D0B0D1803120D09AD0BED180D0B5D189 string (Гар1 Корещ)
- 0x48DDF802 and 0x240A96E01 position.
- 0x100101 learned state, hard key, soft key, and special features.
Stepan Skopivskiy
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.