This presentation details a successful reverse engineering project by Entropia EV and Chaosgriff Tübingen, repurposing old public bus stop displays into dynamic event timetables. The initiative began when donated, often broken, displays were acquired, with initial attempts to hack their complex internal computers proving futile. A breakthrough occurred when the team focused on directly reverse engineering the display's data bus. This involved identifying the UART communication protocol, logging data signals, and iteratively analyzing patterns with Python scripts to decode display messages. The original mainboard was then replaced with an ESP32 microcontroller, running custom Rust-based software designed to fetch event schedules via HTTPS from the Pretalks API and render them. A significant debugging challenge involving inexplicably dark display panels was eventually traced to an "idiotic" software bug: a UART buffer overflow caused message truncation and misinterpretation, inadvertently setting the panel brightness to zero. The project showcases a practical, open-source approach to hardware repurposing, navigating the complexities of embedded development and reverse engineering.
Summarizing the Reverse Engineering of Bus Stop Displays
0:22 Project Goal: The project aimed to reverse engineer old bus stop displays from an unspecified bus company (acquired by Chaosgriff Tübingen and brought to GPN 22) to display custom event timetables.
0:46 Team & Initial Approach: The team included Nina (coordinator), the speaker (software), and Jona (hardware). Initial efforts to hack the complex internal computer of the displays, which contained word processors and radio modules, were unsuccessful.
3:00 Hardware Reverse Engineering Begins: Jona's expertise in electrical engineering led to a shift in focus: directly hacking the display hardware. This involved identifying power and data cables, mapping the system's block diagram (modems, mainboard, LED panels), and recognizing "passthrough" boards as simple plug adapters.
7:06 Choosing the Simplest Interface: The team decided to intervene at the lowest level: the data bus directly feeding the LED panels. This approach avoided the complexity and potential encryption of the main processor's communication.
8:20 Protocol Identification: By soldering wires to the data bus and using a logic analyzer, Jona identified the communication protocol as UART, a common choice for internal microcontroller communication without a dedicated clock.
9:49 Iterative Data Decoding: Logged data was exported as CSV and analyzed with Python scripts. An iterative process of pattern recognition and script refinement allowed the team to decode the display messages, including visualizing individual bits as pixels (e.g., diamonds for '1', dots for '0').
11:23 Bypassing Original Control: The original main processor was disconnected, and an ESP32 microcontroller was introduced. A program was written to emulate the original display messages, which was then iteratively refined to achieve a minimal, functional program capable of sending custom pixel data.
12:47 Software Development in Rust: The custom software for the ESP32 was developed in Rust, utilizing libraries like embassy for asynchronous operations, reckless for embedded HTTP requests, stru for streaming JSON parsing (to handle large data despite RAM constraints), embedded-graphics for rendering, and U8G2 funds for font rendering.
14:48 The "Broken" Display Panels Mystery: During development, some display panels stopped working, appearing faulty. This led to a deeper investigation.
16:03 Microcontroller Decompilation: The firmware from a non-functional panel's microcontroller was read out (luckily, it wasn't copy-protected by the manufacturer) and decompiled using Ghidra. This revealed a specific command (message code 8) that controlled the panel's brightness (values 0-255).
18:10 The "Idiotic" Bug: The root cause was an "idiotic" software bug: a UART output buffer overflow (the ESP32's buffer was 128 bytes, while display frames were 167 bytes). A small gap in transmission after 128 bytes caused subsequent data to be misinterpreted by the panel as a new command, often setting the brightness to zero.
19:07 Positive Experience with Rust: Despite the debugging challenges, the speaker praised the experience of writing asynchronous, memory-safe code on microcontrollers using Rust.
21:37 Remaining Issues & Uniformity: Minor ongoing issues include the ESP32 occasionally losing its WLAN connection (DHCP-related). The software is highly uniform across different displays, requiring only a string change to specify which room's schedule to fetch.
22:11 Source Code Availability: The project's source code is publicly available at Anzeige.ababschurz.Jetzt.
24:13 Brightness Control (Q&A): Brightness can only be controlled on a panel-by-panel basis, not pixel-by-pixel.
24:42 Obtaining Displays (Q&A): Interested parties can contact Chaostreff Twing, with availability depending on the "coolness" of their proposed project.