This talk details the reverse engineering and software development project to repurpose old public bus stop displays into dynamic event schedule boards for hacker communities. Initiated by Chaosgriff Tübingen and continued by Entropia, the effort involved methodically analyzing the complex internal hardware of the displays. Jona, the hardware expert, successfully identified and reverse-engineered the display's internal UART communication protocol, bypassing the more complex onboard computer. Jean then developed custom software in Rust for an ESP32 microcontroller to fetch event data from the Pretalx API, render it, and transmit it to the displays. A significant challenge and key takeaway involved debugging a subtle UART buffer overflow in the Rust code, which inadvertently caused displays to turn off by misinterpreting brightness commands. The presentation also highlights the utility of embedded Rust frameworks and the iterative process of hardware hacking.
Repurposing Bus Stop Displays for Event Schedules: A Reverse Engineering Journey
0:00:22 - Project Goal: The project aims to reverse engineer and reprogram old bus stop displays to show event schedules, such as those for GPN (Gulasch Programmier Nacht), instead of bus timetables.
0:01:09 - Project Inception: The idea originated at GPN 22 when Chaosgriff Tübingen brought several heavy, salvaged bus displays, some damaged, to seek community help in hacking them.
0:02:13 - Initial Hurdles: Early attempts to hack the displays' integrated onboard computers and radio modules proved unsuccessful. Progress was stalled until Jona, with expertise in electrical engineering and reverse engineering, joined the team.
0:03:40 - Hardware Reverse Engineering (Jona): Jona began by disassembling the displays, identifying power and data cables. He mapped the internal data flow from external antennas/modems through a mainboard and "pass-through" boards (which serve as simple connector adapters) to the interconnected LED panels.
0:07:06 - Strategic Hacking Point: Recognizing the complexity of the main PowerPC processor and potential encryption of external communications, Jona focused on the simpler, unencrypted internal display bus – a UART protocol – as the most effective point of intervention.
0:08:34 - Protocol Discovery: Using a logic analyzer, Jona captured signals from the display bus, identified the UART protocol, and decoded the raw bytes being sent from the original mainboard to the LED panels.
0:09:49 - Data Interpretation & Control: Python scripts were developed to analyze patterns in the captured data, allowing visualization of pixel information (e.g., using '#' for '1' and '.' for '0'). This iterative process led to a clear understanding of the display commands and how to send custom pixel data.
0:11:23 - Custom Microcontroller Integration: Jona replaced the original main processor with an ESP32 microcontroller. He programmed it to mimic the essential commands identified, iteratively refining the code to achieve minimal, functional communication.
0:12:45 - Software Development (Jean): Jean developed the display control software in Rust for the ESP32, leveraging its Wi-Fi capabilities for standalone operation. The software fetches event schedules as JSON from the Pretalx API, processes them, and renders the content into display frames.
0:14:06 - "Bamboo Line" & Debugging Challenges: The serial communication to the displays was problematic ("bamboo line") due to interference, requiring significant debugging effort, particularly during the GPN deadline.
0:14:38 - Unexpected Panel Failures: During development, panels began failing, displaying nothing despite receiving data. Initial checks ruled out power supply issues, indicating a deeper problem.
0:16:17 - Firmware Analysis & Brightness Control: Jona reverse-engineered the microcontroller firmware on a "dead" panel using Ghidra. This revealed that a specific UART message (command '8' with a value from 0-255) controlled the panel's brightness.
0:18:07 - Root Cause: UART Buffer Bug: The panel failures were traced to a bug in Jean's Rust code: the ESP32's 128-byte UART output buffer was insufficient for the 167-byte display frames. This caused a transmission gap, leading subsequent data to be misinterpreted as a new command, often setting the brightness to zero.
0:19:04 - Rust Embedded Toolchain: The project utilized the esp-hal, embassy (asynchronous framework), reckless (embedded HTTP client), stru (streaming JSON parser), embedded-graphics (rendering library), and U8G2-fonts within the Rust embedded ecosystem.
0:22:25 - RAM Optimization: Due to Pretalx's HTTPS-only API requiring a substantial crypto stack on the microcontroller, Jean optimized memory usage by utilizing the ESP32's "RAM2".
0:21:40 - Outstanding Issues: Minor issues persist, such as the ESP32 occasionally losing Wi-Fi connection and showing "waiting for DHCP."
0:24:13 - Q&A: Brightness Control: Brightness can only be adjusted per entire panel, not per individual pixel.
0:24:43 - Q&A: Display Availability: Obtaining more displays requires contacting Chaosgriff Tübingen, with availability potentially depending on the proposed project's "coolness."