• Hi everyone !

    I interested in messing with a VGA/HDMI/.. connector & the data exchanged between a device connected to it, read on ! ;p

    As a reminder, EDID looks like that:

    header:          00 ff ff ff ff ff ff 00
    serial number:   50 a6 87 46 e1 0b 04 01 27 19
    version:         01 03
    basic params:    80 10 09 78 0a
    chroma info:     ee 91 a3 54 4c 99 26 0f 50 54
    established:     21 08 00
    standard:        81 80 a9 40 01 01 01 01 01 01 01 01 01 01 01 01
    descriptor 1:
    

    For a current project, I need to:

    • read EDID data from a monitor/tv screen connected over hdmi ( using i2c )
    • modify ( parts of ) this data
    • send this data when requested by other devices connected over hdmi ( using i2c )

    The goal is more or less an "HDMI DDC EDID MitM" ( we can change a lot of infos found in the original EDID )^^
    Along with the above, it should also act as a "fast hdmi switcher", doing EDID handling & messing with hotplug pins ( since EDID is no longer re-read from the monitor when it's switching to a particular source, but instead read once, when the device connecting to the monitor does so in the background )

    my current prototype consists of:

    • a hacked hdmi switch & hdmi breakouts.
    • an original Espruino connected to the monitor/tv screen's hdmi i2c & hotplug pins
    • an Arduino connected to an hdmi 'source' device ( laptop, game console, .. )

    The Espruino listens for a pin rising ( the monitor's hdmi connector's hotplug pin ) before acting as an i2c master to then write & read data a monitor's ( fixed ) i2c adress 0X50.

    The Arduino simulates a 'source' device connection by toggling its hdmi connector's hotplug pin before acting as an i2c slave with address 0x50 & provides EDID data whenever being requested to over i2c.

    I am currently wondering what'd be the simplest & most robust way to communicate between the Espruino & the Arduino ( knowing that having a 3IN<->1OUT hdmi switch, I plan to use 2 more Arduinos, one for each hdmi IN ).
    Every Arduino has only one hdmi device's i2c pins connected to it, and the Espruino is also using different i2c pins to communicate with the screen.

    I hesitate between SPI & serial, and the only limitation ( at least those I see for now .. ) is using a pin for each on the Espruino & using a watch to listen for an Arduino's request of the ( modded ) monitor's EDID ( store within the Espruino's program & refreshed on boot ).

    Moreover, we have limited memory on both the Espruino & the Arduino & although I did get away with modding the Arduino's "Wire" ( i2c ) lib, it seemed I couldn't get more than 256 bytes out of it at once ( and I couldn't figure out if this was coming from the Espruino side ? .. ) & while increasing the buffer seemed to free memory Arduino-side, I still can't get more than ~253 bytes when reading from an i2c address using Espruino ( I still have to run tests using an Arduino as i2c master to better identify the source of the trouble ).

    To bypass this current limitation, I re-wrote the Arduino code to act more like my laptop ( & surely other 'source' devices ) does ( writing a byte to select the portion to be read from i2c, then reading max 128 bytes of data ).

    As the EDID is 128 bytes big & so does the Extended one, writing 0x00 then reading 128 bytes gives to EDID, and writing 0x80 then reading 128 bytes gives to Extended data.
    Also, writing a byte < 256 & then reading a number of bytes gives the n bytes starting from the previously written one ( seems to be the common way for i2c memory chips ? .. ).
    This being said, it seems reading 128 bytes again & again without writing any returns the EDID or the Extended One alternatively in a cycle

    I mostly replicated this behavior ( although I have to fix the code handling switching between sending alternatively each & sending only 128 bytes from a previously received one on the Arduino-side - which works but is still not working wip since it doesn't handle cycling without receiving a byte beforehand for now .. and yet it's not-that-bad-enough to work ;) )

    Once the above was nearly ok, I decided to try scanning the available i2c devices in the monitor, but sadly none of the i2c scanners I found for Espruino worked :/ ..
    .. so I modified a little bit the EDID sniffing code to instead trigger an i2c scan right after sensing a rise on the monitor's hotplog pin & it seems to work, albeit very slow for now
    I'll try to mod an existing i2c scanner to do the work faster & give a prettier output, but part of my other code seems needed, at least for my monitor ( compared to other i2c devices I guess ? .. )

    Code provided below is for:

    • monitor EDID sniffer ( Espruino ): fetches & decodes EDID & E-EDID data
    • monitor i2c addr scanner ( Espruino ): lists i2c peripherials in connected screen
    • EDID fuzzer ( Arduino ): acts as a connected monitor & send EDID data when asked
    • wip js to decode & encode data in the EDID format ( could be improved A LOT .. and it 'll need to if I want it to fit on the original Espruino .. )
About

Avatar for stephaneAG @stephaneAG started