Monday, March 17, 2014

The "Foculus Rift" part 3: Spoofing the EDID

The libOVR SDK recognizes if an Oculus Rift is attached to the PC by checking two particular things:
  1. The USB tracker with the right VendorID, ProductID must be present (this has been solved in Part 2)
  2. The Head Mounted Display (HMD) must be attached, which is nothing more than an ordinary monitor connected over HDMI. The HMD is identified by its so called Extended display identification data (EDID).



Note that the following writeup is specific to changing the EDID data on a RTD2660 based flat panel controller. It involves desoldering and reflashing the I2C chip holding its firmware. There are many things that can go wrong and it is very easy to end up with a bricked device -- so be sure to backup the data before you reflash the chip.

Alternatively, there is a simpler way to spoof the Oculus Rift EDID.
The trick is to directly solder a programmed I2C eeprom to the right pins of the HDMI connector. 
There is a beginner-friendly step-by-step guide by will1384:


Here is the hard way how to do it ...

The EDID is a 128 byte binary blob, which is transferred over an I2C bus to the PC.
This happens when the display is plugged in over a VGA, DVI or HDMI connection.
What is actually stored in this 128 bytes is nicely explained on Wikipedia.

To make the libOVR believe that the generic LCD panel from eBay is actually an Oculus Rift, 
several parameters in the EDID need to be changed.
In particular, the following bytes need to be set to the values read out from an original DK1:
  • Manufacturer ID (byte 8-9)    "OVR"     [0x3E, 0xD2]
  • Manufacturer Product Code (byte 10-11)  [0x01, 0x00]
  • Serial number (byte 12-15)              [0x00, 0x00, 0x00, 0x00]
  • Monitor serial number string            "Serial"  + 0x0A
  • Monitor name string                     "Rift DK" + 0x0A
I didn't want to override the other parameters, as they contain important information about the supported resolutions and color modes of the monitor. However, later I found, that this eBay display controller seems to send incorrect EDID data over the HDMI connection -- which didn't allow me to use it at its native resolution. While I was rewriting the EDID data anyway, I have fixed that mistake.

The RTD2660 is a highly integrated chip, which does the format conversion from an VGA (analog) or HDMI (digital) input to a LVDS output. It also does gamma correction, displays the on-screen menu and many more things. To control all that, it contains a 8051 compatible microcontroller core. The slightly bizarre thing about it is, that the chip does not contain any flash memory for storing the program code. In fact, every instruction is fetched from the nearby W25X40 flash chip over a serial SPI connection on the fly and then executed. It was clear, that the EDID information must be stored in this flash memory.

The LCD flat panel controller board in its original state.
So the first step was to desolder the W25X40 chip and read out its data. Before soldering it back, I placed 300 Ohm SMD resistors between the CLK, MOSI and /CS pins. This allowed me to read and write the chip while it is "in circuit".

W25X40 Flash chip decoupled from the RTD2660 LCD panel controller by 300 Ohm resistors


This allows to read and write the Flash memory without the need for desoldering the chip

The STM32F3DISCOVERY board was used to read and write the flash memory


It turns out, there is over half a megabyte of binary data in there, which is quite a lot of program code for a small 8 bit microcontroller.

For reading (and writing) the chip, one possibility is Ponyprog and an easy to build parallel port interface. Another one is to use the Bus Pirate. I actually used the STM32F3 discovery board, with a custom firmware so it acts like a USB to SPI bridge. With some Python code, I could send commands to the chip and read out its data. If you're interested in the USB to SPI source code, let me know.



Having read out the binary data, I could search through it with a Hex editor. The EDID block always starts with these bytes: 
0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00
So it is quite easy to identify. I found 9 of these blocks! Starting at the following addresses:

(1) 0x00C4F    EDID (128 bytes) sent over VGA
(2) 0x00CFF    EDID (128 bytes) not used. Almost identical to (1)
(3) 0x01E00    EDID + CEA-861 extension block (256 byte) sent over HDMI
(4) 0x10C4F    identical to (1)
(5) 0x10CFF    identical to (2)
(6) 0x20C4F    identical to (1)
(7) 0x20CFF    identical to (2)
(8) 0x30C4F    identical to (1)
(9) 0x30CFF    identical to (2)

I was able to figure out which one is which by comparing the data blocks from the firmware to the EDID data I was reading out in Linux with the get-edid tool. (1) and (2) seemed to contain correct information for the specific LCD panel, which I bought with the controller board -- but (3) was completely wrong and looked like default values which have never been customized.

I modified all of the above EDID blocks and wrote them back to the Flash chip. With this modification, all Oculus Rift compatible games successfully recognize the generic LCD panel as an HMD.

You can find the project files here:

Reprogrammed EDID

This includes the .py files with the commented original and modified EDID data. The binary files of the original and modified Flash image and two iPython notebooks which have been used for the binary manipulations and for flashing the image with the SMT32 board.







10 comments:

  1. Hi again. I flash stm32 with your "stm32f3_hid_template_oku_forReal". Now my pc see board as "Tracker DK", is good?
    I bought this lcd driver boad http://www.ebay.pl/itm/VGA-2AV-Reversing-driver-board-work-for-7inch-800-480-50pin-AT070TN92-Lcd-panel-/181252872721?pt=LH_DefaultDomain_0&hash=item2a33835a11&_uhb=1 without hdmi :(
    I do not know if she has W25X40 chip, but she has this same Realtek.
    In Oculus Configuration Utility now is "No Video Cable Attachted".
    Actualy i waiting for shipping lcd driver board.

    When i will have board,can you help me with them?
    At this moment all is good?

    ReplyDelete
    Replies
    1. If your PC recognizes the STM board as "Tracker DK", then you have done it right! Oculus Rift enabled games should show some head tracking then, even if there is the "No Video Cable Attached" error. Good luck with your HMD. Cheers YFL

      Delete
  2. Very interested/excited about your little project, and intend to give it a try to help with some game development (not everyone on an OpenSource team can afford the Rift).

    I was wondering whether the EDID can just be 'adjusted' on Windows (on Linux I can just recompile the Oculus SDK to get rid of check), it seems that this might be possible via a custom INF for the monitor (see http://msdn.microsoft.com/en-us/library/windows/hardware/jj133967%28v=vs.85%29.aspx).

    ReplyDelete
  3. Is there any way that you could possibly do a quick tutorial on how to do this? I have a STM32F3 and a control board and some soldering knowledge. I'm building a rift myself and this would basically complete it.

    ReplyDelete
  4. If you happen to still have the code for that SPI bridge around, I'd love to have it - I don't have access to anything with a serial port at the moment, and it'd be an awful lot cheaper than buying or building something else.

    ReplyDelete
  5. Hi:) Working on a new VR project that may be highly intriguing! So contact by email name is OMNILOVESTAR at that kinda popular email service that starts with a G. (same company runs blogspot maybe) Pls delete this comment after emailing:)

    By the way, is the edid still working properly with the new rift SDK?

    ReplyDelete
  6. Since SDK 0.4 this method doesn't work anymore. There are two windows drivers now to handle the display and the tracker.
    Do you have any idea to get this working again?
    Thanks!

    ReplyDelete
  7. I made the f Oculus based on your blog! Thank you!!!!!! :)
    http://www.thingiverse.com/thing:664703

    ReplyDelete
  8. Would you be interested in somehow spoofing/injecting the oculus dll to allow any raw data from something like openPIE or TrackIR to pretend to be an oculus? This will allow DIY HMD's to go that one step further. Unfortunately, if the source code isn't released after the official release, we might have a world where developers have to make 50 different releases to support different HMDs. (And the chances of this situation keep rising after the Facebook Buy-Out!)

    ReplyDelete
  9. Can you tell me how to use stm32f3discovery to override (or edit) EDID on display?Thanks

    ReplyDelete