Blackmagic Design makes a lot of video converters in various sizes and feature sets. These are relatively cheap boxes that convert between HDMI, SDI and optical fiber for video signals. There's also some neat converters that can do audio embedding and de-embedding.
Normally these converters are configured using a Windows or OSX utility. Just plug in a converter with an USB cable and change one of the few settings. This is pretty nice except there's no utility for Linux.
Making a Linux utility
I already maintain pyatem/openswitcher which is a reverse engineered protocol implementation for the ATEM video switcher devices from Blackmagic Design. I decided to also take a look at the USB protocol for the converters to add this to the pyatem python library.
I started by looking at the BiDirectional SDI/HDMI 12G micro converter. To look at the traffic I installed USBPCap on a Windows machine. This is not the most convenient tool but it's the quickest way to get USB logs.
With USBPCap running I started the official software and changed every setting once and then ended the capture. With this captured traffic I could start to look at how the protocol works using Wireshark.
The protocol is relatively simple, it only uses USB control transfers and retrieving/writing settings is done by sending a setting name to the device and then reading or writing the value.
The more difficult part of this design is that you need to know in advance which settings exist on which converter. There does not seem to be a way to enumerate a list of the settings from the device.
Using this information I wrote the
pyatem.converter module that implements the USB protocol using libusb and also added a definition that describes all the settings for the BiDirectional converter I used.
With the library implemented I greated a simple GTK3 application that presented the settings in a similar way to the official software:
Supporting more hardware
A setup utility that only works with one model of converters is not super useful. It also creates the risk of overfitting the library to some specific protocol quirk that one model has, and this is exactly what happened in this case.
I ordered the HDMI to SDI and SDI to HDMI 3G converters since these are cheap and really common. They are also an older generation of converters. For those not familiar with this hardware: the 12G converters are the 4K capable ones and the 3G converters top out at 1080p30. The number refers to the link speed.
I created another packet dump using Windows to find which fields are supported and to my suprise the protocol for these converters is completely different.
The protocol for these 3G converters does not work by sending a setting name and then a value. Instead the settings are numbers and the operation is done in a single usb transaction. This is possible since a numeric setting can be set in the wValue field of a read or write operation to signify what you want to read or write.
Due to this I had to refactor the whole library to support multiple protocol backends. This would also make it possible to support more kinds of Blackmagic USB protocols for their different products like the ATEM Mini hardware and the monitors. These are normally configured using seperate setup utilities.
Since I also work on postmarketOS I tried running my Linux app on a PinePhone. The only change I had to make it removing the "Blackmagic Design" name from the converter name because the product names are so ridiculously long. After that the Linux desktop setup utility I made Just Works(tm) on Linux phones:
After sharing this picture there seemed a bit of interest for having a mobile app for configuring the converters. This makes a lot of sense, the converters are usually spread out all over the place and dragging a laptop around to configure them is annoying.
While it's nice that this works on postmarketOS supported phones, the majority of people still have Android and iOS phones. Since I already know how the protocol works and doing a simple Android app shouldn't be too hard... I decided to learn Android development.
The Android app
I had tried to do Android development before and always got stuck very early in the process making me never continue it. It seems like Kotlin is a great improvement over the Java issues I was having though. I managed to get a proof of concept up and running that read the settings in a single converter in a day and continued developing. I also signed up for a Google Play developer account and went through the verification steps. It turns out dealing with the Google Play Console is definetly the hardest and most time consuming part of development.
It took about a week to get everything on the google side verified and reviewed. Luckily I did this with by first hello world demo and didn't wait until I had finished the rest of the app otherwise I would've lost a lot more time on this. In the week of waiting I fixed up the multi-protocol setup and refactored the code of the app to be actually nice instead of one large MainActivity.kt file with hardcoded values.
My plan with the Android app is to make it paid and keep the opensource Linux app and libraries free. This makes me able to fund the development of the open source side through the Android app and give a wider audience the ability to actually use the app. The nice thing is that the Play store already takes care of all the payment and licensing for this.I can just keep using the funds from the Android app to get more hardware to reverse engineer and add to the app.
The Android app is now in open beta. The beta can be joined through https://play.google.com/apps/testing/nl.brixit.setup. Currently the app only supports the three converters mentioned above but I hope to provide an update soon to at least get the UpDownCross converter working.
I'm not planning to make an iOS app for this though, that would require me to buy into the Apple ecosystem with multiple devices to even get started and learn a whole new software stack. I'm also not entirely sure if apps controlling non-class-compliant usb hardware is even possible in the Apple mobile ecosystem.