Hacker News new | comments | show | ask | jobs | submit login
Reading a VGA monitor's configuration data with I2C and a PocketBeagle (righto.com)
121 points by robin_reala 7 months ago | hide | past | web | favorite | 24 comments



If you have HDMI, the EDID comes through on the DDC which is just I2C. You can read it with a BusPirate or any decent LA: https://www.extron.com/company/article.aspx?id=uedid

HDCP also happens over this interface, so it’s trivial to snoop on the key exchange: https://github.com/ApertureLabsLtd/hdmi-sniff/blob/master/RE...

CEC (control devices via HDMI) happens on a separate channel using a proto also similar to I2C: http://www.quantumdata.com/pdf/CEC_White_Paper.pdf

There are a few good ~cheap CEC adapters for HDMI out there. I’ve used the PulseEight one since they have decent library support plus a CLI. You can also use the HDMI port on a Raspberry Pi to play with CEC: https://github.com/Pulse-Eight/libcec/blob/master/docs/READM...


I came across a monitor with an EDID that was out of the spec for what constitutes a valid EDID, and it actually exposed a bug in the linux i915 driver, I had all this corrupted output.

While the patch was getting merged, I was able to dump the EDID, edit it to be within spec, and then was able to actually flash it BACK to the monitor by using nothing other than this program on github [1], and the HDMI port on a Dell E6430.

I was amazed that was possible to write an EDID from simply connecting to the port, didn't need to open anything up, was able to do it without any special equipment, etc.. I never realized how complicated some of these display protocols can be, but part of it is just i2c, and I guess the hardware is not very restrictive on how that i2c controller can be used outside of display purposes.

Someone with a Raspberry Pi could go around a college campus and wreak havoc if they wanted. Goes to show you that you should not trust any public peripheral, not ever. That's especially important in the age of USB-C and mobile devices where charging and data are put on the same port.

[1]: https://github.com/bulletmark/edid-rw


Oh it's so much worse than that. The EDID is typically implemented with an I2C EEPROM connected directly to the AUX lines. The "edid read" procedure is no more than reading "0xA0", the standard EEPROM I2C address, over AUX. The first time I ever sniffed that bus and saw a simple "read" command to that address I'd seen in so many other places before I almost fell off my chair.


Editing a monitor's EDID data would be a sneaky attack. Someone might never figure out why their monitor suddenly became monochrome or only supported 640x480. Or you could gaslight someone by making the resolution a bit worse every day.


There should be a write protect for the EDID on displays. A display I was working with didn't have the write protect enabled and my Nvidia graphics card decided to overwrite the EDID for me. Had to reprogram it before my PC would recognize the display again.


Speaking of DDC, this little utillity is really handy for changing the brightness of third party monitors on macOS: https://github.com/kfix/ddcctl

There are probably more fancy things out there that integrate via .prefpane or something, but works good enough for me.


The equivalent for Linux users are ddccontrol and ddcutil.

https://github.com/ddccontrol/ddccontrol

https://github.com/rockowitz/ddcutil



You can also use the Debian package i2c-tools to communicate with things connected to the busses on your computer.

I once used it to play with a set of Melexis IR sensors I'd soldered to the VGA port on a crap video card. It made writing the Arduino code way easier after figuring out all the hard things with Linux. There was even enough power on the VGA pin to run 4 of them!

Really though, it was just exciting to be able to wire some of my own hardware into the computer and write a program to talk to it. Made me feel like I actually own my computer again.


Author cited a Wiki page as technical reference. Worth noting that VESA has made the EDID standard--including errata and other relevant standards--readily accessible to the general public[1]. Now if only they'd do the same for the latest revision of DisplayPort...

[1] https://www.vesa.org/vesa-standards/

Asks for name, country, and e-mail address, but otherwise immediately redirects to downloadable content directory.


On most linux systems, "read-edid" or "get-edid" will give you this information.


Yes, plugging the monitor into a Linux box would have be easier. In my case the edid is exposed under /sys, and edid-decode is from the xorg-x11-utils Fedora package

$ edid-decode < /sys/devices/pci0000:00/0000:00:03.0/0000:0f:00.0/drm/card0/card0-HDMI-A-1/edid

Extracted contents:

header: 00 ff ff ff ff ff ff 00

serial number: 00 b3 00 37 00 00 00 00 01 19

... [ followed by more data and the decoded output ] ...


> plugging the monitor into a Linux box would have be easier

As JFK said, we do these things not because they are easy, but because they are hard :-)


Even on Linux things don't always work as intended. The reason I am familiar with the EDID information is that my display stopped working after a kernel update and I tried to figure out why. It turned out that my AV receiver didn't like the VIC field being sent in the HDMI infoframes[1]. There is a surprising amount of communication which goes on between the graphics card and the monitor in a modern system.

1: Bug 50371 - [BISECTED] HDMI display blank unless VIC set in AVI infoframe

https://bugzilla.kernel.org/show_bug.cgi?id=50371


modprobe i2c-dev and you can access the i2c bus your monitor is on in the same way described in this post w/o hacking up your cable.


I2C is a really beautiful protocol, and it shows up all kinds of interesting places - I had no ideal that monitors used it for EDID!


I use it in my personal projects a lot, it's very easy to code up an i2c master and/or slave on pretty much any microcontroller. Very handy for abstracting different sensors or actuators by hiding them behind a microcontroller that bridges them to a common i2c bus. Not to mention that boat loads of sensors use the protocol directly. SPI is even simpler, but it requires more wires and also is lower level (SPI is basically just a fancy shift register) so it usually ends up taking more boilerplate.


>To read the data over I2C, I used the PocketBeagle, a tiny Linux computer that I had handy. (You could use a different system that supports I2C, such as the Raspberry Pi, Beaglebone or Arduino.)

I keep hearing that the Raspberry Pi's peripheral support for things like I2C is pretty bad - is that no longer the case?

It's a pretty easy interface to bit-bang and not too sensitive to the clock line's precision, but it's nice when you can actually use a chip's hardware peripheral as intended.


Perhaps you are thinking of the I2C clock stretching bug[1]?

Bugs like these are not unusual in embedded systems. It is often difficult to fix the hardware and the software will implement some kind of workaround. The web page lists several possible workarounds for this bug.

1: http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.ht...


For VGA I2C one could use the HDMI port. I think it's called dtoverlay=i2c2_yes_i_know_what_i_am_doing or similar.


Something satisfying about talking/listening to hardware.

Seems somehow more "real".

Should have gone into writing drivers but that always seemed so damned tedious. ;/


This is awesome! I have to try this.


This would be a cool FPGA project as most boards include an FPGA port.


Cutting a cable and going through all this effort is stupid when you can probably get the data using your graphics card.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: