The goal of this project is designing an electronic device, which can record states of multimedia buttons on steering wheel. It also is a BLE HID keyboard to a paired smartphone. Every time a button on the steering wheel is pressed, smartphone should receive a physical keyboard key press event - in this case a SCAN NEXT/PREV TRACK. This should work fine with any media player on smartphone that is running at the moment, in my case Samsung Music or Spotify.
Chevy Volt is a very complicated car, also when it comes to it's communication buses. It is equipped with 2 obd2 ports on driver and passenger side. Those ports expose various CAN and SWCAN buses, more about them here.
Mine primary focus is on a low-speed SWCAN bus on pin 1. It is not like a classic CAN bus, because signal is carried on one wire, with signal levels relative to chassis ground. But fortunately standard CAN hardware like transcievers can be interfaced with it. To make it work all grounds have to be connected together, and also CAN LOW termninal has to be connected to ground. CAN HIGH connects to SWCAN (pin 1 in OBD2 connector). More on GMLAN/SWCAN here
To make it all work I have to determine what data gets transmitted on the bus when I press a button on the steering wheel. To do it I made an analyzer from a cheap MCP2515 CAN-SPI module and Raspberry pi. CAN module needed a little modification to work with 3,3V from Pi. With a help of a driver, we can get CAN bus in linux, visible as a native network interface with a help of SocketCAN support in current linux kernel. To analyze captured data we can use Wireshark or command line tools from package can-utils. I choose the second way, but I warn everybody that it's harder to configure, since you have to compile can-utils from source. apt-get on raspberry pi downloads very old version of package, which does not have support for 29-bit CAN IDs. Clone git repository, and This link might help with compilation and installation process. Beware, also a libtool package is needed to execute scripts succesfully)
With working and newest version of can-utils I can start sniffing. I enabled interface can0 with command
sudo ip link set can0 up type can bitrate 33300
and then used cansniffer application from can-utils package
cansniffer can0 -c
I use my raspberry pi without a screen, so all was done via ssh. At first a huge list of CAN IDs transmitting data showed up. But to minimize amount of data transmitted on the CAN bus, I turned vehicle off, opened the drivers door and waited a while for all modules to go to sleep. Then I turned on the radio with a button on dashboard. Big amount of data showed up in cansniffer, but because it disappears after a moment of inactivity (data not changing for given ID), a list cleared itself to a few rows after a moment. After a few clicks on steering wheel I got CAN ID i was searching for.
ID 10438040(hex) is transmitting one byte of data on every steering wheel multimedia button event. Event type is determined by this byte's value:
01-vol up pressed
03-next track pressed
04-previous track pressed
05-audio source pressed
Criuse control buttons seem to be on another CAN bus, or need car to be turned on - i haven't seen any chages when pressing them in cansniffer.
My intent is to use 03, and 04 messages, since rest of them still triggers actions in stock radio/infotainment (on AUX prev/next track does nothing). Next step is to make an embedded sniffer with some microcontroller to sniff data only from 0x10438040 CAN ID.