Skip to content
Tigo edited this page Jun 15, 2025 · 3 revisions

The V-Link app can be controlled using steering wheel controls. Depending on your car, the buttons communicate on the CAN- or LIN-bus.

To setup LIN-based steering wheel controls, stay on this page. Otherwise, check out the Controls section of the CAN BUS integration page.

To use LIN you will need to connect the LIN Bus pin that contains the steering wheel control messages (Usually connected to the Steering Wheel Module (SWM)) to the V-Link HAT or to a LIN transceiver like the MCP2004. In P1 Volvo's, connector A of the ICM (Infotainment Control Module) behind the the waterfall contains the steering wheel messages/commands and is easy to access.

If you're not using the HAT and want to connect the MCP2004 to the Raspberry Pi, make sure to connect it through a 3v3 logic level converter to step the Tx signal down to 3.3V, to avoid damaging GPIO pins on your Raspberry Pi. It's also possible to connect the MCP2004 to an Arduino (Leonardo, Pro Micro) instead. These Arduino boards are inexpensive and run at 5V, so you don't need a logic level converter. The Arduino can convert/emulate the car's steering wheel controls into USB/HID keyboard presses which can ultimately control the V-Link app, CarPlay, Android Auto etc.

ICM_CONNECTOR_IMAGE

JSON File Configuration

You can configure the LIN-bus integration in V-Link using the file /v-link/backend/lin.json.

The configuration file follows a structured JSON format. Below is an example:

{
    "type": "interface",
    "name": "lin",
    "swm_id": "0x20",
    "sync_id": "0x55",
    "zero_code": "0xFF",
    "ign_on": ["0x50", "0x0E", "0x00", "0xF1"],
    "long_press_duration": 1500,
    "click_timeout": 300,

    "commands": {
        "button": {
            "BTN_NEXT":  ["0x20", "0x00", "0x10", "0x00", "0x00"],
            "BTN_PREV":  ["0x20", "0x00", "0x02", "0x00", "0x00"],
            "BTN_VOL_UP":  ["0x20", "0x00", "0x00", "0x01", "0x00"],
            "BTN_VOL_DOWN":  ["0x20", "0x00", "0x80", "0x00", "0x00"],
            "BTN_BACK":  ["0x20", "0x00", "0x01", "0x00", "0x00"],
            "BTN_ENTER":  ["0x20", "0x00", "0x08", "0x00", "0x00"]
        },
        "joystick": {
            "BTN_UP": ["0x20", "0x01", "0x00", "0x00", "0x00"],
            "BTN_DOWN": ["0x20", "0x02", "0x00", "0x00", "0x00"],
            "BTN_LEFT": ["0x20", "0x04", "0x00", "0x00", "0x00"],
            "BTN_RIGHT": ["0x20", "0x08", "0x00", "0x00", "0x00"] 
        }
    }
}

swm_id

  • The ID of the Steering wheel module. Filter for LIN frames from the steering wheel

sync_id

  • ID indicating an incoming LIN frame

zero_code

  • ID indicating the end of a LIN frame was reached

ign_on

  • Not used

click_timeout

  • The amount of time (in milliseconds) before a click is registered

long_press_duration

  • The amount of time (in milliseconds) before a second action is performed

commands

  • Key-value pairs of button names and associated LIN frames. Only supports single LIN frames (unlike the CAN integration)

V-Link Wiki

Clone this wiki locally