Please keep in mind that I can take no responsibility for errors on this page or damage, the instructions on this page might cause. The information is provided without warranty - but I promise that its to my best knowledge. If you have suggestions or questions - feel free to contact me. I hope it helps.
I was challenged with the following problem some days ago at my working place:
There is a Terminal Server System that needs to serve different sessions with different screen resolutions. That is usually not a big deal with homogeneous environments like Windows' RDP on Windows Clients or Apples ADP on Apple Clients - it can get tricky though when using an Apple Server with Linux/Windows Clients (because people are avoiding OS X here a lot and want to use Linux more often).
Apple does to my knowledge not provide ADP Clients for Platforms other than OS X (just mentioning that Microsoft provides a pretty nice RDP Client for OS X). So if you want to work remotely with multiple persons on the same Mac, you are stuck with third party software that provides virtual desktop access with a protocol other than ADP. There are some out there and all have some flaws. The best matching solution for us was iRAPP TS (here) which shares a flaw with most other solutions: It can - as far as our experience went - not provide virtual desktops with arbitrary screen resolutions, but only with resolutions, that are supported by an attached physical screen. Thats bad.
Many Users of this solutions have wide 21" Displays, many others have 4:3 20" high resolution displays - both are quite expensive, so attaching a blind real display to the terminal server is not the preferred option: building a virtual Monitor out of what is lying around in the drawer is.
I chose using VGA, because its very well adaptable to any current display connection and connectors are easily availble. With DVI, this is not the case, with HDMI, they are quite expensive and additionally, they are quite hard to solder. To sum it up: the same rules apply to VGA, DVI and HDMI - but NOT to DisplayPort.
So to the shopping list we add 1 VGA connector and casing - choose a gender you like.
In connection with this approach, 3 main questions arose.
- What, from the point of view of a general VGA-Port, defines an attached display?
- How to trick the VGA-Port into thinking, there was a Display attached?
- How to trick the VGA-Port into detecting a proper Model that supports the right resolutions?
To answer the first question, I dug deep in my memories of former similar projects. When I was fiddling with VGA. I remembered, that there was a loop somewhere in the connection, that was established when the VGA Cable was connected to the graphics card - but I found out that this memory was quite misleading:
Most VGA Ports detect a Monitor by looking at the actual signal output pins. These are usually broadband HF lines with a specific impedance (75 ohm for the three color signals, around 700 ohm for the two synchronisation signals). The logic behind the port can detect the state of the lines, wether they are floating (not connected) or properly terminated (connected) and probably some other states as well. Most ports seem to look at the state of the "green" line, to detect a connected display.
This might be, because the older monochrome displays of the earlier days often only had the green line connected. The green line was favored in some other cases, too. The most prominent one is "Sync on green", which was popular with individually connected BNC displays, although I never really understood, why the extra line was such a problem.
Concerning question two: Although it would probably be enough just to terminate the green line with about 75ohm, I concluded the answer to this question to be proper termination of all HF lines. I don't like floating signals, especially in HF environments. Everything is an antenna - and yet again, I don't know the specific layout of the output drivers. They might dislike floating lines, too.
So to the shopping list we add 3x 82ohm (and optionally 2x 680 ohm) medium precision resistors
If you just want an attached display to be (falsely) detected, you are done with your simulator now. Here, one of the differences between DVI/HDMI and VGA is worth noting: They do not sample the signal lines to detect an attached display, but have a seperate hot-plug pin, that has to be pulled high (to DDC VCC for example) using a resistor. If you want a display with specific properties to be detected, you have to get digital - and answer question three.
How does a VGA-Port talk to the display to find out what it is capable of? Which protocol is used? Is there a standard? The answers are EDID (Extended Display Identification Data) and DDC2 (Display Data Channel version 2). DDC2 is the protocol and method, EDID the data transfered. both are explained in the Wikipedia in detail.
Source: Wikipedia |
The most important thing about DDC2 to know is, that its actually an I2C bus on the VGA port, getting the EDID from a industry standard 1kBit I2C EEPROM at address 80 (0x50) - usually this chip is write protected - and thats a good thing in most cases. All lines necessary to read the EEPROM are present on the VGA connector. These are VCC (5v pin9), GND (pin5 or pin10, documentations vary), SDA (I2C data, pin 12) and SCL (I2C clock, pin 15). That is convenient for two things:
- We don't need any external wiring - everything we need is already on the connector
- In case of a normal display, detection is possible in the moment of connecting it. No external power is required on the display side - the I2C EEPROM does not have to be connected to the displays circuits.
The most important thing about EDID to know is, that is a pretty well defined bit-mapped 128byte data structure, that does not only contain Model number, serial and manufacturing date of the display, but also supported modes and nowadays also native resolutions of TFT-displays and preferred resolutions. Its format according to version 1.3 is what we want to focus on and is also very well explained in the linked Wikipedia article. It does support everything, a virtual display will need.
At this point, several other question arise:
- Where to get valid EDID to program into the display?
- How to get the EDID onto a chip?
- How to make modifications to that data?
The first one is easy to answer, if you have a original display that suits your needs, a newer Intel Graphics Adapter and a reasonably new Linux operating system. Since the Linux Intel Kernel Module - at least for i915 and newer - exports the I2C-buses from the connectors (VGA, DVI, HDMI) to the Linux kernel and that way is a quite available and easy-to-access multi I2C bus master. This has come in quite handy for many small projects I have built :). Other graphics boards (some ATI, probably others) do the same thing, but I will stick with the Intel explanation, because I have it in my notebook.
You need the i915 kernel module (or which ever works for you) that talks to the graphics card as well as the i2c-dev kernel module, that provides device access to the I2C buses. The I2C-tools come in handy to find the right bus, because modern graphics cards will export a terrifying number of buses to the kernel - most of them are not working or not for us to fiddle with. For my notebooks graphics adapter its 7 buses. Only 2 of them are usable - the one for the VGA Port and - what surprised me a little - the one for the internal LCD-panel.
Connect the display, you want to clone the data from to your VGA-Port or whichever port you have chosen. Use
to list the available buses. Choose one you like, then try
to scan it. If device 0x50 shows up, you might be in luck.
I hacked together a small script, that eases the steps to answer questions 1 and 2 a little. It reads all data from 0x50 on a specific bus into a file or writes data from a file into that device. It can also dump a file and analyze its contents, which might also help with question 3.
Find that tool here:
Its a python script that uses python-smbus and some pretty standard libraries to work on the chip. While I am writing this, I change the script pretty much every minute, but I promise: reading and writing a chip works. There is also some detailed EDID dumps, that you can use to find out, what information is in the EDID structure. To read data into a file, use the following command - assuming, your bus is "2":
which will read the EEPROM contents into the file eeprom.bin
There goes question one. Question two needs your dummy plug to get detected. Then its a simple
and you have a copy of your monitor. You can play around with the "dump" and "ranges" commands of the script a little bit. They give some insight into the data structure of the EEPROM. For that you have to have compatible I2C EEPROM that can be wired to work on address 0x50. So put for example a AT24C02 on your shopping list and wire it up.
Let's postpone question three a little while and sum up what we found out so far:
Connect the display, you want to clone the data from to your VGA-Port or whichever port you have chosen. Use
i2cdetect -l
to list the available buses. Choose one you like, then try
i2cdetect <busid>
to scan it. If device 0x50 shows up, you might be in luck.
I hacked together a small script, that eases the steps to answer questions 1 and 2 a little. It reads all data from 0x50 on a specific bus into a file or writes data from a file into that device. It can also dump a file and analyze its contents, which might also help with question 3.
Find that tool here:
Its a python script that uses python-smbus and some pretty standard libraries to work on the chip. While I am writing this, I change the script pretty much every minute, but I promise: reading and writing a chip works. There is also some detailed EDID dumps, that you can use to find out, what information is in the EDID structure. To read data into a file, use the following command - assuming, your bus is "2":
./EDID_manager.py read 2 eeprom.bin
which will read the EEPROM contents into the file eeprom.bin
There goes question one. Question two needs your dummy plug to get detected. Then its a simple
./EDID_manager.py write 2 eeprom.bin
and you have a copy of your monitor. You can play around with the "dump" and "ranges" commands of the script a little bit. They give some insight into the data structure of the EEPROM. For that you have to have compatible I2C EEPROM that can be wired to work on address 0x50. So put for example a AT24C02 on your shopping list and wire it up.
Let's postpone question three a little while and sum up what we found out so far:
- Regarding VGA, we need to terminate at least the Green analogue line with a little more than 75 Ohm to get our plug detected.
- The detection of monitor capabilities is done using an I2C EEPROM on the VGA display side
- The EEPROM contains a 128-256Byte data structure we need to copy
That is only 3 steps to clone your display - and you got all the tools. So get cracking!
But to get back to question 3: How to modify the data? Basically all you need is a hex editor and some knowledge of the data structure - and the documentation in the Wikipedia helps a lot. But there are some caveats and they stink:
- Some Information is redundant in the EDID - for example the display size, timing information, sync types and some other things you may stumble across. Make them match each other (at least nearly).
- Some Information you can put in there can describe physically impossible scenarios. Try not to do that. Read some additionals about timing of analog RGB signals. Keep in Mind things like horizontal / vertical blanking, the pixel clock and their relations. This is especially the case, if you don't want a dummy plug, but for example want to build an adapter, that attaches to an actual display that has no DDC yet (I still have some of these). If you screw things up really bad, you might break a trusty CRT.
- Do not mix dumps of digital displays with analog ports. It might not hurt, but it also might as well. There are some interface specific data fields that describe the interface. These have different meanings for digital or analog interfaces - for example the information about the level of the RGB-Outputs is sitting in 2 bits that are reserved on digital interfaces. Anything could happen.
- Try to verify the structure (you may use my tool, you may use any other - I had a lot of fun building it, you might as well have a lot of fun using it.) before using it on actual hardware. The parsers and verifiers are not perfect, but may help to determine faulty data in your file.
- Graphics adapters are a real pain in the b*** when it comes to verbosity. They might silently reject the information in the EDID or parts of that. It might also get overridden by software. For fixes and preventive measures: read point 4 again and think it over. :)
A favor I ask - Please, if you dump the EEPROM of your monitor, send it to me, together with make and model of the display it belongs to. It might help me to understand the data structures better and improve the tool. Thank you very much.
Drop me a message, if you have a pull request, dump from your display or a question.
You may use this blog's comment function or send me an email: sua-edid-32b37f1c at w2o.jjim.de