Reverse engineering an LCD wall’s communications protocol
Not satisfied with 80s-style consumer IR control? I’m not.
I want to build a modern wireless tablet setup & control for a newly-acquired LCD Wall product.
In order to do that, I need to find out more about the proprietary communications protocol behind it.
Finding the original software

After checking google for software for hours, I tracked down the original control software by emailing the manufacturer, who sent us a handy Dropbox link to the latest software version. That was easy enough!
Run the software and see what happens

Through an obscure username/password combination, some somewhat broken translation and needless complexity in the software, I worked out how to make it function just fine.
But that’s not modern enough- it would be confusing for staff operating it, and far less efficient than it could be. There’s still room for improvement..
Starting to reverse engineer the software
For this particular software, there were some obvious signs it was a .NET application- it used an SQLite database, it contained a number of .NET specific files within the folder, and named .NET in the text file with the passwords from the last step.
I dug in to a free .NET decompiler — ILSpy (https://github.com/icsharpcode/ILSpy) — to see if this was the right path to go down. Opening the executable in ILSpy showed the resources, but not the code in the way I expected.

The manufacturer has used an obfuscater called ConfuserEx to try to prevent reverse engineering of this software.
Luckily most obsfucation software like this is only a slight annoyance and can be reversed- in this case, an existing bit of software called NoFuserEx provided the assistance I needed. Once I ran the .exe through NoFuserEx, I got…

A much more useful result for us.
Digging through the code to find what is needed

When setting up these particular monitors, the first has direct Ethernet control- the rest link through with RS232 (serial) connection.
Each individual monitor takes an identical video input, and then displays only the part of the video image relevant to where it is on the wall- in this way, one video signal can be spanned across multiple monitors.

Initially, none of the panels knows where it is located on the wall, and therefore they don’t know which part of the image they are supposed to display.
The software has a “Set ID” function that, according to the manual, takes a four-digit temporary code displayed on the screen and allows you to use that to tell the monitors where they are physically positioned in that grid.
The software splits the four-digit code on the TV in to two parts (Code1 and Code2), and then asks you for an LcdId- which is a two digit number consisting of the column followed by the row that you want to move that display to.
The code for this popup is found under EditLCDViewModel

This code sets up a six-byte array with some values, and then runs it through a SendMsg method which eventually send the command to the monitor.
Initially the byte array looks like:
213, byte.MaxValue, 0, 0, 0, 170
byte.MaxValue is always 255, so it can be written as:
215, 255, 0, 0, 0, 170
The code then proceeds to update the three zeros with the contents of Code1, Code2 and LcdId such that you get:
215, 255, Code1, Code2, LcdId, 170
So for example, if the screen is displaying code 1234, and you want it to be in column 2, row 5, you should send:
215, 255, 12, 34, 25, 170
So let’s test that out in a small program to check that it works!
A quick test in Go to make sure it’s correct
From the software setup dialogs, I already know that the default IP address on the monitor is 192.168.0.66, and the default communications port is TCP Port 1024. So now all that’s left to do is write some code.


The code runs, and all works to plan! All you have to do is run the command, entering the wall dimensions, and a list of the codes in order from left to right, top to bottom, and the hard work is done for you!
Next Steps?
Right now you still need to use the remote to display the codes on the monitors, making this code not so useful.

Thankfully, the menu can be triggered through IP as well.

Once that’s in place and working, I’ll get to the task of writing a small iPad app using Flutter that can streamline this setup.
Less time spent fussing on the tech on-site so there’s more time to spend on more important things!
UPDATE: I created a list of useful network commands discovered at:
https://themodernmachine.nyc3.digitaloceanspaces.com/PJ-B551P-V6F%20Seamless%20Monitor%20Network%20Protocol.pdf
If you liked any of the content here, please leave some feedback on Medium or get in contact!
