Two years ago today, I open sourced BlueRetro [1] v0.1 in the context of the Hackaday Prizes 2020 [2]. Up to that point I had been working on the project for about a year in private. So we could say BlueRetro is three years old now! Let’s do a small retrospective!
What is BlueRetro?
BlueRetro is a multiplayer Bluetooth controllers adapter for various retro game consoles. Lost or broken controllers? Reproduction too expensive? Need those rare and obscure accessories? Just use the Bluetooth devices you already got! The project is open source hardware & software under the CERN-OHL-P-2.0 & Apache-2.0 licenses respectively. It’s built for the popular ESP32 chip. Wii, Switch, PS3, PS4, PS5, Xbox One, Xbox Series X|S & generic HID Bluetooth (BR/EDR & LE) devices are supported. Parallel 1P (NeoGeo, Supergun, JAMMA, Handheld, etc), Parallel 2P (Atari 2600/7800, Master System, etc), NES, PCE / TG16, Mega Drive / Genesis, SNES, CD-i, 3DO, Jaguar, Saturn, PSX, PC-FX, JVS (Arcade), Virtual Boy, N64, Dreamcast, PS2, GameCube & Wii extension are supported with simultaneous 4+ players using a single adapter.
At a very young age I somehow got really fascinated by game controllers. I recall my dad fixing Atari 2600 controllers by replacing the contact domes and showing me at the same time how the wiring worked. I recall being mind blow at the fact that, for each generation of console released, the button count kept going up while the number of wires in the cables kept going down! Some magic was going on in those black chips for sure!
By the time I got to colleges, I understood pretty much how all controller protocols worked except those using Bluetooth. I forked the Cube64 [3] project and started adding new features. After graduating, I worked professionally on 802.11 (Wi-Fi) testing & driver development for almost 10 years and I still had very little knowledge about Bluetooth besides knowing it was frequency hopping in the 2.4 GHz spectrum (Annoying interference!).
So leaning Bluetooth was a major factor why I started this project. Another reason was that I always wanted to maintain a significant open source project. I felt like a universal and multiplayer Bluetooth adapter was a missing piece in the retro gaming ecosystem and that, if successful, the project could really catch on. Finally, selling a hardware product done entirely by myself was a professional goal I had ever since I started my engineering studies.
Learning how Bluetooth protocol worked had a major impact on how I decided to develop BlueRetro. My first reflex as someone having previously worked with 802.11 devices was to try to get a wireless trace of a controller connecting to my Linux laptop. The first thing I leaned here is that true wireless trace isn’t much of a thing in the BT world and that making a trace of the HCI layer [4] is much easier and give you pretty much all you care for as a developer. Looking at the trace, I saw that after a long dance of packets between the two devices at the beginning, the end result was simply the controller sending status packets at some interval without any intervention from the host.
I had chosen to go with the ESP32 chip [5] and the Bluetooth stack that is included in the ESP-IDF is Bluedroid. Going through the sources and the docs my first impression was that it was quite bloated and I didn’t really see how it was going to help me in the simple task of getting reports from a HID device. I looked at the USB_Host_Shield_2.0 [6] project which had its own Bluetooth stack and had support for the most common Bluetooth controller but in the end I felt it was a bit too messy for my taste. I also looked at BlueKitchen’s BTstack [7] for a few seconds until I noticed the non-free license.
Base on my perception that nothing complex was going in the HCI trace and that none of the Bluetooth stack I reviewed pick up my interest, I naively decided to make my own! I thought I just needed to mock enough of the protocols in a stateless fashion until the controller started to send the HID report. Plus I felt I would learn much more this way and I did! The first version of the project only supported the WiiU Pro controller. The BT stack was pretty much a mock over the HCI interface at first. But progressively as I added support for more devices it became much more dynamic and closer to a proper Bluetooth stack with the notable quirk of supporting only HID devices.
That may sound like a hard way to do it but in retrospect I think writing my own stack allowed me to learn at my own pace and was the easiest way to get a deep understanding of the various protocols involve with using HID devices. When I use an existing library, I rely a lot on examples and I don’t really know what I’m doing until I face an issue that requires digging into the library internal. You essentially cross your finger it won’t break.
Having my own stack made it much easier IMHO to support console controllers quirks. 7th generation console controllers like PS3 (No inquiry mode, require magic command) and Wii (PIN is BDADDR, no proper HID descriptor, requires configuration) are base on Bluetooth but don’t really fully follow the standard for a proper BT HID devices. 8th gen and over consoles offer a dumb-down standard HID interface but also got a more feature rich proprietary mode (Rumble, player LEDs, etc.).
On the other hand, it put on me the burden of supporting standard devices like mouse and keyboard. That may sound like a one-time effort to add support for something “standard,” in really I keep getting reports weekly of some random devices not working due to some wrong assumption I made in the generic device code. The fixes are always trivial but I can see I would likely avoid those issues entirely by using an existing mature stack.
For the first year after making the project open, my focus was still to turn this into a product I was going to sell myself. A few people attempted to make their own adapter base on my hardware design b