使用树莓派修改HDMI虚拟插头的EDID
Modifying an HDMI dummy plug's EDID using a Raspberry Pi

原始链接: https://www.downtowndougbrown.com/2025/06/modifying-an-hdmi-dummy-plugs-edid-using-a-raspberry-pi/

我需要将一个廉价的HDMI虚拟插头模拟的显示器从4K更改为1080p。虚拟插头通过存储在I2C EEPROM上的EDID数据来模拟连接的显示器。 我使用树莓派Zero访问连接到HDMI端口的I2C总线。首先,我安装了`i2c-tools`和`raspi-config`。然后,使用`i2cdetect`,我验证了虚拟插头的EDID EEPROM在地址0x50被识别。 接下来,我使用`get-edid`将虚拟插头的原始EDID转储到一个文件中。我重复了同样的过程,将1080p HDMI采集设备的EDID转储出来。 最后,我使用`i2cset`在一个`bash`循环中将采集设备的EDID写入虚拟插头的EEPROM,有效地替换了其原始的4K EDID。验证步骤确认了重新编程的成功。虚拟插头现在模拟了采集设备,解决了我的问题。此技术也可用于将旧的虚拟插头升级为支持4K,但在通过I2C修改显示器数据时应谨慎操作。

Hacker News 的一个帖子讨论了如何使用树莓派修改 HDMI 虚拟头,以便为无头系统模拟显示器连接。用户指出,廉价的虚拟头 EEPROM 容量有限(256 字节),不足以支持高分辨率/高刷新率(超过 1080p60),并且可能需要硬件修改才能写入。一个关键限制是缺乏 HDCP 支持,这使其无法与需要内容保护的视频流应用一起使用。 帖子中提到了其他方法,例如协商 HDCP 的 HDMI 分线器和“HDCP 脱衣器”,尽管有些可能会降级到旧版本的 HDCP。讨论还扩展到修改实际显示器的 EDID,这是一个可能存在风险的过程,因为存在写保护,尽管一些现代显示器使用微控制器而不是 EEPROM,并且并非设计为可重写的。 软件创建的虚拟显示器被提出作为替代方案,但这可能很复杂,并且可能无法在所有操作系统和 GPU 组合中都能正常工作。讨论最后探讨了 DisplayPort EDID 模拟以及可用的工具。
相关文章

原文

I recently found myself needing to change the monitor that a cheap HDMI “dummy plug” pretended to be. It was a random one I had bought on Amazon several years ago that acted as a 4K monitor, and I needed it to be something simpler that didn’t support a 4K resolution. The story behind why is a long one that I’m still figuring out and might eventually become a separate blog post in the future.

If you’re not familiar with dummy plugs, here’s a quick primer: they are tiny dongles you can plug into an HDMI, DVI, etc. port that don’t actually do anything with the video signal. They simply have the minimum circuitry needed for a video source device, like a computer, to think that a monitor is hooked up. In general this entails a pull-up resistor on pin 19 (HPD) to +5V, as well as a little I2C EEPROM chip containing the Extended Display Identification Data (EDID). This is useful for headless machines to force the OS to think a monitor is attached.

The EDID contains all the info about the monitor: the manufacturer, manufacture date, supported resolutions, audio channels, color space, and stuff like that. My goal was to replace the dummy plug’s EDID with an identical copy of an EDID from one of my many 1080p HDMI capture devices. Then, the computer I plugged it into would think the capture device was plugged in instead of a 4K monitor, and everything would be hunky dory.

I wasn’t sure if the dummy plug’s EDID EEPROM would be programmable, but I decided to give it a shot. There was a chance that it would have its write-protect pin configured to disable programming, but I figured it wouldn’t hurt to try.

Conveniently, I found that my Raspberry Pi Zero has an I2C controller wired to the correct pins on its HDMI port. This makes sense — the Pi would need to be able to read the EDID of an attached monitor. This post on the Raspberry Pi Forums and this GitHub comment were helpful for explaining which I2C controller(s) to look at in software on various Pi devices:

Before I go further, I want to make it clear that it may be possible to screw up a monitor if you follow these instructions while a real monitor is plugged in and it doesn’t have its EDID protected. Be careful to only run these commands if you have something attached to the HDMI port that you’re not afraid of bricking, such as a dummy plug! Also, make sure you are confident you’re on the correct I2C bus! Always read the EDID and parse it first to make sure it actually contains an EDID before you attempt a write. If you attempt these commands on a PC, it’s possible that you could accidentally flash hardware that isn’t an EDID, like a RAM module’s SPD EEPROM.

Starting from a fresh Raspberry Pi OS Lite install, I performed the following modifications:

  • sudo raspi-config
  • sudo apt install i2c-tools
    • Unfortunately, this requires network access, which creates a bit of a problem if you are on a Pi Zero. You might need a USB-Ethernet adapter to make this happen. Another slightly crazy option is to temporarily take the SD card out of your Pi, put it into your desktop PC running Debian/Ubuntu, run sudo apt install binfmt-support qemu-user-static on your PC, chroot into the SD card’s rootfs (options 1.3 and 2.1 worked for me), and run the apt install command inside of the chroot.

And with those prerequisites out of the way, I was ready to start tinkering with the dummy plug’s EEPROM. Note that I also needed an HDMI-to-Mini-HDMI adapter.

Since I was using a Raspberry Pi Zero, I chose bus 2. You could change the number below to something else on a different model, as listed above (e.g. 20 or 21 on a Pi 4).

I ran i2cdetect to see if the EDID EEPROM was recognized:

This came back with the following result, showing that an I2C device was detected at address 0x50, which is exactly the address used for EDID:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Interestingly, this particular dummy plug also responds with addresses 0x51 through 0x57 present. These other addresses seem to contain copies of the same EDID. Not all dummy plugs show up like this — another one I have only detects 0x50. Anyway, next, I dumped the original EDID from it:

get-edid -b $edid_i2c > edid-orig.bin
2
This is read-edid version 3.0.2. Prepare for some fun.
Attempting to use i2c interface
Only trying 2 as per your request.
256-byte EDID successfully retrieved from i2c bus 2
Looks like i2c was successful. Have a good day.

Nice! To make sure I got a good dump, I tried it twice and compared the results to make sure they were identical. Then I printed it in a format suitable for copying/pasting to something like edidreader.com:

od -v -An -txC edid-orig.bin

This spit out a nice little hex dump of the EDID that was stored on it:

 00 ff ff ff ff ff ff 00 1a ae 31 9d 00 00 00 00
01 19 01 04 85 58 31 78 3e a4 fd ab 4e 42 a6 26
0d 47 4a 2f cf 00 e1 c0 d1 c0 b3 00 a9 40 95 00
81 80 81 40 81 c0 02 3a 80 18 71 38 2d 40 58 2c
45 00 e0 0e 11 00 00 1e 4d d0 00 a0 f0 70 3e 80
30 20 35 00 c0 1c 32 00 00 1a 00 00 00 fc 00 48
44 4d 49 20 4d 6f 6e 69 74 6f 72 0a 00 00 00 10
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 4a
02 03 46 70 52 e1 60 5f 5d e6 65 64 62 10 04 03
1f 20 21 22 13 12 01 26 09 7f 07 11 7f 50 83 01
00 00 6e b9 14 00 40 00 18 78 20 00 60 01 02 03
04 67 d8 5d c4 01 78 00 07 6c 03 0c 00 20 00 f0
78 20 00 40 01 04 08 e8 00 30 f2 70 5a 80 b0 58
8a 10 c0 1c 32 00 00 1e b7 e6 ff 18 f1 70 5a 80
58 2c 8a 00 ff 1c 32 00 00 1e 56 5e 00 a0 a0 a0
29 50 30 20 35 00 80 68 21 00 00 1a 00 00 00 e9

Pasting it into the site linked above, I could see it was a valid EDID:

Now that I was confident I had the dummy plug’s original EDID backed up, I unplugged it from the Pi’s HDMI port and plugged my capture device in instead, and repeated the exact same procedure to dump its EDID:

get-edid -b $edid_i2c > edid-capture-card.bin

I confirmed it was also a valid EDID. Finally, I unplugged the capture device and connected the dummy plug again, and wrote the capture device’s EDID to it with this fun little code snippet. There are tools out there that can probably do this more efficiently, but hey, this works and doesn’t require any special packages other than the standard userspace Linux I2C tools and bash or dash!

edidbytes=($(od -v -An -txC edid-capture-card.bin))
for i in "${!edidbytes[@]}"; do
	byte=0x${edidbytes[$i]}
	echo Writing byte $i: $byte...
	i2cset -f -y $edid_i2c 0x50 $i $byte
done

As a quick explanation, this reads the entire EDID (probably 256 bytes in size) from the dump file created earlier, and formats it into an array of two-digit hex strings using od. Each entry in the array represents one byte in the EDID. Then it loops over each byte, prepending a “0x” prefix and writing it out to the EEPROM using i2cset.

After running this code, I re-read the EDID from the dummy plug and checked to see if it matched the file I started from:

get-edid -b $edid_i2c > edid-test.bin
diff edid-test.bin edid-capture-card.bin

The diff command produced no output at all, which indicated that the new dump was identical. The dummy plug’s EEPROM had successfully been reprogrammed with the EDID from my capture device!

Of course, at this point I anxiously plugged it into my test computer, powered the computer up, and noticed that everything was great and it acted as though my HDMI capture device was plugged in instead of a 4K monitor. Success!

I thought I’d share this procedure in case it’s useful for someone else in the future. You could probably also use this solution to go in the opposite direction — upgrading an old 1080p dummy plug to add 4K support. Again, be careful with these commands! I wouldn’t recommend tinkering with I2C writes on an actual PC. Use a Raspberry Pi so you don’t accidentally brick your desktop PC.

联系我们 contact @ memedata.com