The VESS is the Virtual Engine Sound System found in many KIA and Hyundai branded vehicles. A system like VESS has been required by law for electric vehicles (EVs) since 2020 by EU law.
This research is not aimed at disabling VESS as you can do that very simply by just unplugging it. The work here is some reverse engineering based on the physical inspection only.
This work was done during the Christmas holiday of 2021.
A nice future roadmap might be to control the volume and change the sound:
- By flashing new SPI contents directly
- Using the onboard serial debug port
- Using ISO-TP over CAN
- Using the OBD II port
We know the device broadcasts using CID: 0x5E3 (1507d), with an 8 * 0x00 broadcast data.
Many thanks to Eric Reuter with open source code.
- Does that make the request
5E3-8=5DB
?
Maybe using ISO-TP for multiple data packets?
- Speed -
0x524
(1316d) - Gear -
0x200
(512d)
Using RS485 CAN HAT:
sudo ip link set can0 type can bitrate 500000 restart-ms 100
sudo ip link set up can0
I cut the box but left the connector attached. I might want to connect this to my car in the future and those friction-fit pins looked fragile.
Removing the conformal coating was really fun.
Notable components:
Analog BF706CCPZ
, 400MHz 1Mb SRAM DSP.
Macronix MX25L3235E
, 32Mbit flash chip.
NXP A42/3C,TJA1042
CAN transceiver.
JRC NJU7291
system reset IC with watchdog timer.
ST FDA803D
, 1x45W class D amplifier.
Unlabelled 5V power regulator, for audio?
- 05 → filtered 12V in?
- 04 → unknown
- 03 →
GND
- 02 → unknown
- 01 → U102:VCC
Unknown, marked 11S XAG
, 3V3 MCU power regulator
- 01 → 4K6 resistor then
STB
- 04 →
U102:VCC
- 06 →
U102:SPLIT
Unknown, marked D41 X03
, 5V CAN power regulator. Note: this seems to be power phased from U109.
- 01 →
CN100:1
i.e.VDD_EXT
- 04 →
U102:VCC
1.27mm socket, similar to SHR-12V-S-B
, used as debug port presumably for factory
programming.
- 01,
VDD_EXT
- 02,
R317
→SYS_HWRST
- 03,
R117
→PB_09
→UART0_RX
- 04,
R116
→PB_08
→UART0_TX
- 05,
JTG_TDO_SWO
- 06,
JTG_TCK_SWCLK
- 07,
JTG_TDI
- 08,
JTG_TMS_SWDIO
- 09,
JTG_TRST
- 10,
GND
- 11,
WDEN
[10K to GND] - 12,
nc
Connected to SYS_HWRST
which triggers a CPU reset.
4 3 2 [1]
8 7 6 5
- 01,
Battery+
- 02,
IG1
→D101
→ MOSFET - 03,
SWI
→ Schottky diode (protected input?) - 04,
P-CAN High
→U102:7
- 05,
GND
- 06,
GND
- 07,
IND
→R194
(460R) - 08,
P-CAN Low
→U102:6
Connecting a 3.3v RS-232 adaptor to UART0_RX
and UART0_TX
at 115200 baud
gives a repeated:
>---------------------------------------------------------<
> <
> VESS Firmware 88.0201 <
> <
>---------------------------------------------------------<
...and this loops forever, unless WDEN
is pulled to MCU VCC (3V3).
Powering the module using Battery+
gives the same output, but also pushing
IGN
up to 12V the additional prompt appears:
$ tio /dev/ttyUSB0
>---------------------------------------------------------<
> <
> VESS Firmware 88.0201 <
> <
>---------------------------------------------------------<
VESS>>
/************************************************************/
HELP : Display command list
POWERIC : Power amp IC control
VESS : VESS Sound Output Control
RHEOSTAT : VESS LED PWM Control
STATUS : VESS Internal Status
ALLFLAT : Flat EQ setting
SOUNDTEST : 20km/h sound output
SOUNDSETTING : display output sound setting
GOTOUPDATER : goto reprogramming mode
SAVETEST : save sound output setting to flash memory
READSETTING : read sound output setting from flash memory
EOLTEST : writing YYMMDD to flash memory
Lib Version: 2
File: ..\src\main.c | Line: 106 | Function: help
Build Date: Jan 14 2019 | Build Time: 07:54:38
/************************************************************/
======= CAN & I/O =======
CarRdy : 0
GarSelDisp : 0
WhlSpdFL_Kph : 0
WhlSpdFR_Kph : 0
PTOperModforECU : 7
Avail Spd : 200.000000
Detentout : 0
RheostatLevel : 0
IntTailAct : 0
VESS Switch Input : 1
TCU1(gear) Input : 0
HEV_CP6(detent,rheo) Input : 0
HCU1(ready,PTmode) Input : 0
CGW2(tail) Input : 0
========== etc ==========
VESS Switch On/Off Status: 1
7V Det port value: 1
18V Det port value: 1
7V Det Status: 0
18V Det Status: 0
ucLEDstep: 20
ucOpenLoadDetected: 1
ucShortLoadDetected: 0
ucOffsetDetected: 0
Updater Cnt : 65535
====== Product Info ======
date : 2019/08/31
Part No. : 96390-G5650
CAN DB ver : 0.40
HW ver : 01.01
PowerIC Read/Write
1. Write register 2. Read register 3. Unmute 4. Mute 5. Power limit
6. PWM switching Freq/Dithering/Phase
2
====Power IC====
PowerIC Register(0x00) : 0x00
PowerIC Register(0x01) : 0x41
PowerIC Register(0x02) : 0x00
PowerIC Register(0x03) : 0x1B
PowerIC Register(0x04) : 0x00
PowerIC Register(0x05) : 0x00
PowerIC Register(0x06) : 0x80
PowerIC Register(0x07) : 0x00
PowerIC Register(0x08) : 0x21
PowerIC Register(0x09) : 0x00
PowerIC Register(0x0A) : 0x40
PowerIC Register(0x0B) : 0x00
PowerIC Register(0x0C) : 0x00
PowerIC Register(0x0D) : 0x00
PowerIC Register(0x0E) : 0x07
====Power IC====
PowerIC Register(0x20) : 0x00
PowerIC Register(0x21) : 0x08
PowerIC Register(0x22) : 0x01
5
Input MAX voltage scale
1.OFF, 2.15%, 3.30%, 4.40%, 5.50%, 6.60%, 7.70%, 8.80%, ESC to exit
6
Select PWM switching frequency at 48KHz
1.336, 2.384, 3.432
Select PWM clock dithering
1.ON, 2.OFF
Not selected
Select PWM phase
1.In phase, 2.Out of phase
Not selected
Note, PowerIC Register(0x22) changes from 0x0 when muted to 0x01 when unmuted.
/************************************************************/
VESS
Control Speed : '<' Decrease, '>' Increase
Forward/Reverse : '?' Toggle Forward/Reverse
Gain Slew Enable/Disable : '/' Toggle Enable/Disable
/************************************************************/
PWM Control
> : Increase rheostat stage
< : Decrease rheostat stage
/ : Automatic rheostat stage change
Speed dependent volume off
Sound Test 20km/h
1. Sound Generation 2. Sound Stop
1
Start Sound output
2
Stop Sound output
======= Sound Setting =======
fbegin[0]: 0.000000
fEnd[0]: 15.000000
fConstant[0]: 0.249870
bCharacter[0]: 0
bReverse[0]: 0
NumPoint[0]: 7
UserGain / dB[0]: 1.000000 / 31.000000
UserSpeed[0]: 0.101563
UserGain / dB[1]: 1.000000 / 25.000000
UserSpeed[1]: 2.500000
UserGain / dB[2]: 1.000000 / 19.000000
UserSpeed[2]: 5.000000
UserGain / dB[3]: 1.000000 / 19.000000
UserSpeed[3]: 7.500000
UserGain / dB[4]: 1.000000 / 19.000000
UserSpeed[4]: 10.000000
UserGain / dB[5]: 1.000000 / 19.000000
UserSpeed[5]: 12.500000
UserGain / dB[6]: 1.000000 / 0.000000
UserSpeed[6]: 15.000000
fbegin[1]: 10.000000
fEnd[1]: 25.000000
fConstant[1]: 0.249870
bCharacter[1]: 0
bReverse[1]: 0
NumPoint[1]: 7
UserGain / dB[0]: 1.000000 / 0.000000
UserSpeed[0]: 10.000000
UserGain / dB[1]: 1.000000 / 15.000000
UserSpeed[1]: 12.500000
UserGain / dB[2]: 1.000000 / 11.000000
UserSpeed[2]: 15.000000
UserGain / dB[3]: 1.000000 / 11.000000
UserSpeed[3]: 17.500000
UserGain / dB[4]: 1.000000 / 11.000000
UserSpeed[4]: 20.000000
UserGain / dB[5]: 1.000000 / 15.000000
UserSpeed[5]: 22.500000
UserGain / dB[6]: 1.000000 / 0.000000
UserSpeed[6]: 25.000000
fbegin[2]: 20.000000
fEnd[2]: 35.000000
fConstant[2]: 0.249991
bCharacter[2]: 0
bReverse[2]: 0
NumPoint[2]: 7
UserGain / dB[0]: 1.000000 / 0.000000
UserSpeed[0]: 20.000000
UserGain / dB[1]: 1.000000 / 0.000000
UserSpeed[1]: 22.500000
UserGain / dB[2]: 1.000000 / 0.000000
UserSpeed[2]: 25.000000
UserGain / dB[3]: 1.000000 / 0.000000
UserSpeed[3]: 27.500000
UserGain / dB[4]: 1.000000 / 0.000000
UserSpeed[4]: 30.000000
UserGain / dB[5]: 1.000000 / 0.000000
UserSpeed[5]: 32.500000
UserGain / dB[6]: 1.000000 / 0.000000
UserSpeed[6]: 35.000000
fbegin[3]: 0.000000
fEnd[3]: 35.000000
fConstant[3]: 0.583327
bCharacter[3]: 1
bReverse[3]: 0
NumPoint[3]: 15
UserGain / dB[0]: 1.000000 / 36.000000
UserSpeed[0]: 0.000000
UserGain / dB[1]: 1.000000 / 34.000000
UserSpeed[1]: 2.500000
UserGain / dB[2]: 1.000000 / 30.000000
UserSpeed[2]: 5.000000
UserGain / dB[3]: 1.000000 / 28.000000
UserSpeed[3]: 7.500000
UserGain / dB[4]: 1.000000 / 26.000000
UserSpeed[4]: 10.000000
UserGain / dB[5]: 1.000000 / 26.000000
UserSpeed[5]: 12.500000
UserGain / dB[6]: 1.000000 / 26.000000
UserSpeed[6]: 15.000000
UserGain / dB[7]: 1.000000 / 25.000000
UserSpeed[7]: 17.500000
UserGain / dB[8]: 1.000000 / 25.000000
UserSpeed[8]: 20.000000
UserGain / dB[9]: 1.000000 / 31.000000
UserSpeed[9]: 22.500000
UserGain / dB[10]: 1.000000 / 0.000000
UserSpeed[10]: 25.000000
UserGain / dB[11]: 1.000000 / 0.000000
UserSpeed[11]: 27.500000
UserGain / dB[12]: 1.000000 / 0.000000
UserSpeed[12]: 30.000000
UserGain / dB[13]: 1.000000 / 0.000000
UserSpeed[13]: 32.500000
UserGain / dB[14]: 1.000000 / 0.000000
UserSpeed[14]: 35.000000
fbegin[4]: 0.000000
fEnd[4]: 35.000000
fConstant[4]: 0.583327
bCharacter[4]: 1
bReverse[4]: 0
NumPoint[4]: 15
UserGain / dB[0]: 1.000000 / 35.000000
UserSpeed[0]: 0.101563
UserGain / dB[1]: 1.000000 / 33.000000
UserSpeed[1]: 2.500000
UserGain / dB[2]: 1.000000 / 31.000000
UserSpeed[2]: 5.000000
UserGain / dB[3]: 1.000000 / 29.000000
UserSpeed[3]: 7.500000
UserGain / dB[4]: 1.000000 / 27.000000
UserSpeed[4]: 10.000000
UserGain / dB[5]: 1.000000 / 26.000000
UserSpeed[5]: 12.500000
UserGain / dB[6]: 1.000000 / 25.000000
UserSpeed[6]: 15.000000
UserGain / dB[7]: 1.000000 / 24.000000
UserSpeed[7]: 17.500000
UserGain / dB[8]: 1.000000 / 23.000000
UserSpeed[8]: 20.000000
UserGain / dB[9]: 1.000000 / 27.000000
UserSpeed[9]: 22.500000
UserGain / dB[10]: 1.000000 / 0.000000
UserSpeed[10]: 25.000000
UserGain / dB[11]: 1.000000 / 0.000000
UserSpeed[11]: 27.500000
UserGain / dB[12]: 1.000000 / 0.000000
UserSpeed[12]: 30.000000
UserGain / dB[13]: 1.000000 / 0.000000
UserSpeed[13]: 32.500000
UserGain / dB[14]: 1.000000 / 0.000000
UserSpeed[14]: 35.000000
fbegin[5]: 0.000000
fEnd[5]: 0.000000
fConstant[5]: 0.000000
bCharacter[5]: 0
bReverse[5]: 1
NumPoint[5]: 7
UserGain / dB[0]: 1.000000 / 12.000000
UserSpeed[0]: 0.000000
UserGain / dB[1]: 1.000000 / 10.000000
UserSpeed[1]: 35.000000
UserGain / dB[2]: 1.000000 / 10.000000
UserSpeed[2]: 100.000000
UserGain / dB[3]: 1.000000 / 0.000000
UserSpeed[3]: 0.000000
UserGain / dB[4]: 1.000000 / 0.000000
UserSpeed[4]: 0.000000
UserGain / dB[5]: 1.000000 / 0.000000
UserSpeed[5]: 0.000000
UserGain / dB[6]: 1.000000 / 0.000000
UserSpeed[6]: 0.000000
Read
Read end
,8888oo.
Y8888888o.
Y888888888L
Y8888888888L
888888888888L
d8888888888888.
]888888888888888.
]888888888PP''''
]8888888P' .
,ooooo. ]88888P ,ooooooo88b.
,8888888p ]8888P ,8888888888888o
d88P'888[ ooo' oooo. _oooo. ooo oop ]888P `'' ,888P8888888o
,888 J88P J88P d8P88 d88P888 ,88P,88P `P'' ,88P' ,888888888L
d888o88P' 888' ,8P,88 ,88P 88P d88b88P __ d88888[ _o8888888P8888.
,8888888. J88P 88'd8P d88 '' ,88888P d8' d888888888888888P 88PYb.
d88P 888P 888' d8P 88[,88P ,o_ d88888. ,8P d8888P' 88888P' P' ]8b_
,888']888'J88P d888888 d88'J88',88Pd88b JP d888P 888P',op , d88P
d8888888P d88bo.,88P'Y8P 888o88P d88']88b d' ,8P'_odb ''',d8P _o8P ,P',,d8L
PPPPPPP' `PPPPP YPP PPP `PPPP' <PPP `PPP ,P 88o88888. ,o888' o888 d888888.
d' d888888888888888L_o88888L_,o888888888b.
dP d888888888888888888888888888888888888888o
dd8' ,888888888888888888888888888888888888888888L
d88P d88888888888888888888888888888888888888888888.
File: ..\src\main.c | Line: 82 | Function: Logo
Build Date: Jan 14 2019 | Build Time: 07:54:38
The full dump of the SPI device is here.
ASCII strings are here, some of which look super interesting.
$ binwalk backup.bin
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
467552 0x72260 Microsoft executable, MS-DOS
There is raw audio data in the flash from 0x100000 which is similar to what is found in the Ioniq. To hear it, load into Audacity as "raw data" as 1-channel, signed 16 bit PCM.
Although the ADSP chip is a BF70x, and I attempted to reverse engineer the bytecode with Ghidra:
- Install javac using
sudo dnf install java-11-openjdk-devel
- Download ghidra_10.0.4_PUBLIC
- Download gradle 7.3.3
- Clone https://github.com/sualk/ghidra-blackfin
- Build the extension
GHIDRA_INSTALL_DIR=ghidra_10.0.4_PUBLIC ./gradle-7.3.3/bin/gradle
Then install the extension in Ghidra and restart it. Then import backup.bin
. Then we get junk, as
we're trying to decompile bytecode for the BF52x...