So I started down this road for a few reasons, one work orientated and one completely based on my own curiosity. I needed to find a way to sniff I2C traffic at boot time for work, and thought I could check if the MSI RGB lights were controlled via I2C. The MSI Gaming App lets you change the colors from Windows, so there must be some communication underneath. I figured they woudn’t be re-inventing the wheel so…Serial? SMBus/I2C? Well, I needed to do the I2C work anyway, so that was my first approach.

I knew PCIe has SMBus clock and data lines so started by using an adapter where these were routed to a header, but got nothing. I even tried an extender cable and probing the PCIe socket itself, but could not get an clock signal. Immediately this was a bit strange, as the VGA card in the machine is visible when dumping the I2C slaves from linux, but I could not see any clock on the PCIe pins. My next plan of attack was DDR. I knew it appears on I2C to provide various capabilities but wasn’t sure if I could utilize this or not…turns out I could!

A quick mention, I would not have been able to do this without the soldering capabilities of a co-worker, so a big thank you to him. Looking at this DDr4 datasheet we can see pin 141 (SCL) and pin 285 (SDA) are the I2C pins we’re after, so lets see if we get anything from them.

So here is our newly soldered Corsair LPX 16GB DDR4 (2333Mhz) I2C sniffer module. But does it work? To find out I hooked up a picoscope to the outer most pin on the 3 pin header to see if I could get a clock reading. I fired up the Picoscope beta software on Linux and…

Well it definitely looks like a clock to me. In all honesty I was amazed it worked after the failed attempt on the PCIe connector, so lets put it to work and see if we can decode some I2C traffic from the Ryzen system. The quick solution for a test was hook up a Saleae logic analyzer, and run their Logic software. This comes with some basic decoding analyzers so should give us a good indication that our sniffing attempt is getting a good enough signal to do some proper work with. I was able to create some traffic with i2c-tools on the Ryzen system which is currently running Arch Linux.

Things rarely ever just work when you’re being a bit silly, but this is all going pretty well. The next step is to use something to actively monitor and decode the data, the Raspberry Pi has an I2C with 2 of the GPIOs functioning as SCL and SDA, so lets put something together.

So after enabling I2C on the pi with raspi-config I then dumped the bus from the ArchLinux Ryzen system, and then the same on the RPi. Here are the outputs top and bottom to compare.

At this point, it’s just unusual, everything is still just working how it should. The RPI is on the Ryzen systems I2C bus via wires soldered on to a DDR4 module, I mean yeah the DDR4 module isn’t registering with the system, but it has a giant antenna on its i2c pins so that’s fair enough. For now it’s a sacrafice for science, it might work OK when the wires are removed though…we’ll see. (Edit: It did.)

So now all there is to do is put something together that will dump all the traffic on the bus in a readable form. For this I turned to PIGPIO, which if I’m being honest took too long to realise was Pi-GPIO. I found some demo code on a forum for a python script, however the I2C is a 2-wire protocol, with the SDA activity compared to the SLC level determines START and STOP states. The python loop was simply not fast enough to deal with the callbacks from PIGPIO and would often mis-interpret I2C starts / stops.

There was C code to achieve the same thing, so I opted for that to attempt to dump the data. I modified the format of the output to make it more obvious what operations were happening. I will pop the modified code up on github at some point in the future if anyone is interested. So lets have a look at a Ryzen / MSI B350 boot from the I2C bus perspective (ignore the DATA/NACKs, part of uploading to github LATER is the error in my C code)..

So that satisfies the work project, but what about that motherboard RGB header? Well unfortunately, there is zero I2C communication when the MSI Gaming App changes the colors on the RGB header. It’s unforunate that this was a dead end, but I have a few more avenues for exploration.

I have reveresed the MSI Gaming APP and I do have my own C# application which uses the MSI libraries underneath, but they are still a black box. Again the code will be up on GitHub when I reduce some of the complexity that comes in from experimenting.

I hope this was interesting to anyone looking at I2C comms. I will update this entry when the code is on GitHub, and I’ll probably do an entirely separate post about the C program that runs on the RPi its-self.

–Martin