Blog Post
Developing wtfos packages.
February 05, 2023 - 9 min read
fpv.wtf is an open source project that aims to bring the best possible experience to the DJI FPV system. The creators developed a method to gain root access to the DJI FPV System and have developed a framework called wtfos that includes anti-bricking, a configurator, a package manager and more allowing for custom packages to be built for the goggles, air unit, and vista to extend their functionality beyond what DJI intended.
As part of our open source initiative, we have developed a few of these packages and open sourced them for the fpv.wtf/wtfos project, and this blog post is going to show you how to get started with developing your own package, and how to get it published on the fpv.wtf configurator website.
Our Packages
auto-naco
Automatically enables FCC mode when you power on your fpv system, giving you the best possible range and performance without the hassle of having to use a computer and sd card to enable it.View on Github
avin-mods
A mod built around the AV Input functionality on the DJI FPV Goggles, Allowing for some indepth customization and fixes for some of the biggest annoyances with the AV Input.View on Github
image-configurator
Allows you to change the background/splash screen image and the screensaver images for that extra bit of customization on your fpv system.Sister Package to image-changer
View on Github
Developing Packages
Getting started with developing packages for WTFOS is easy. The packages are based on OpenWRT Opkg Package Manager, a fork of ipkg. Opkg is a full package manager for the root file system on embedded devices. It is primarily used to install, upgrade, remove, and list packages on embedded devices. As such, the file format is very simple, being a few tarballs inside a tarball.
wtfos is built to be completely opensource software, with developers from all over the world contributing to the project. With the ability to develop your own packages, the possibilities opened for the DJI FPV system are endless.
The following steps will walk you through the process of developing your own package for the DJI FPV system, they are by no means comprehensive, but should be enough to get you started on your journey to developing your own package.
Step 0: Decide on what you want to build
The DJI FPV system at it's core is an extremely slimmed down build of the Android Kernel, using a shared architecture based on DJI's P1 SoC between the Goggles, Air Unit, and Vista. This ultimately leaves a lot of room for customization and modification, even as far as running doom on the goggles, Your imagination really is the limit, for this example we will be creating a sort of "Hello World" package that will play a little tune when you power on your goggles.
Step 1: Create a new package
To create a new package, we will start with a template package that is already setup for WTFOS. You can find the template package by stylesuxx on GitHub stylesuxx/ipk-example. Clone the repo to a new directory and rename it to the name of your package, for this example we will be using hello-world-tune
.
Step 2: Setup your workspace
At a minimum you will need ADB and Make installed on your system.
You can download ADB from the Android Developer Website, or if on Linux you can install it by running sudo apt-get install android-tools-adb
Make can be installed on windows by downloading the MinGW compiler, or on Linux by running sudo apt-get install build-essential
.
If you are going to be coding your package in C or C++ you will need to have Android NDK r23
- ndk-build
installed on your system, however, packages can also be written in plain bash scripts, we will be using a bash script for this example to keep things simple.
Step 3: Configuring your package
First, we need to change the package name in the control/control
file, this is the name that will be used to install the package, so we will change it to hello-world-tune
.
We also need to change the package description, this is the description that will be shown on the fpv.wtf configurator website and when you run opkg list-installed
on your goggles, so we will change it to Plays a little tune when you power on your goggles
.
And finally, we need to specify that the package depends on dinit
, this is the init system that is used on the goggles and is required for the package to run when the goggles are powered on.
Your control file should now look something like this:
Package: hello-world-tune
Version: 1.1.0
Maintainer: D3VL <[email protected]>
Description: Plays a little tune when you power on your goggles
Architecture: pigeon-glasses
Homepage: https://github.com/d3vl/wtfos-hello-world-tune
Depends: dinit
⚠️ Make sure you're using LF line endings, not CRLF line endings, this can cause issues with the package on the goggles! ⚠️
Step 4: Reverse engineering the functionality
Once you have your workspace ready, we need to figure out how to actually make the goggles play a tune. Thankfully DJI left some clues for us in the /system/bin
directory of the goggles, we can see that there is a file called test_buzzer.sh
, this is a file left over from the development of the goggles and is used to test the buzzer on the goggles. We can use this file as a reference to figure out how to make the goggles play a tune.
Checking the file we can see a call to a binary called test_pwm
test_pwm 0 2349 50 1 $on
For the purpose of this example we will use the same binary to play the tune, however, if we wanted a more robust solution we could open this binary in a disassembler such as Ghidra and figure out how it works and write our own binary to play the tune, this is an exercise left to the reader. Here's a hint of what you may find though, /sys/class/pwm/pwmchip0/pwm0
😉
Authors Note
DJI Has left a lot of files from development scattered around the goggles and au's, the binaries even have debug symbols left in them, so if you are looking for a way to do something have a good dig around the /system/bin
directory of the goggles and au, you may find what you are looking for, make sure you also have a look on the fpv.wtf wiki as it's already packed with findings!
For additional help you can also join the fpv.wtf Discord and ask for help in the one of the development channels.
Step 5: Writing the package
Now that we know how to make the goggles play a tone we can write our script, we will be using a bash script for this example, but you can also write your package in C or C++ if you prefer.
Executables should be placed in the data/opt/bin
directory of your package.
Make a file called hello-world-tune.sh
in the data/opt/bin
directory and add the following code to it:
#!/bin/sh
# Play a little tune when you power on your goggles
test_pwm 0 2349 50 1 1 # on
sleep 0.1 # wait 0.1 seconds
test_pwm 0 2349 50 1 0 # off
sleep 0.5 # wait 0.5 seconds
test_pwm 0 2349 50 1 1 # on
sleep 1.5 # wait 1.5 seconds
test_pwm 0 2349 50 1 0 # off
sleep 0.5 # wait 0.5 seconds
test_pwm 0 2349 50 1 1 # on
sleep 0.1 # wait 0.1 seconds
test_pwm 0 2349 50 1 0 # off
You can test this script by running it on your goggles before building the package, to do this you will need to connect your goggles to your computer via USB and run the following command:
adb push hello-world-tune.sh /tmp/hello-world-tune.sh
We use the /tmp
directory because it is cleared on reboot, this is a safety measure to prevent us from leaving any files on the goggles that could cause issues and saves us from making the filesystem messy while developing.
Once the file is copied to the goggles you will need to access the goggles root shell by running the following command:
adb shell
Once you are in the goggles root shell you can test the script by running the following commands:
chmod +x /tmp/hello-world-tune.sh
./tmp/hello-world-tune.sh
If everything is working correctly you should hear a little tune play when you run the script!
Step 6: Making the package run on boot
Making it run on boot is as simple as creating a few files to let dinit know about the package
First, make a file called hello-world-tune
in the data/opt/etc/dinit.d/
directory of your package and add the following lines:
type = scripted
command = /opt/bin/hello-world-tune.sh
This file tells dinit that the package is a scripted
package and that the script to run is /opt/bin/hello-world-tune.sh
which is the path to the script we just created after it's installed on the goggles.
scripted
packages run once and then exit, if you wanted the package to run and restart automatically if it exits you could use process
instead of scripted
. You can find more information on the dinit manual.
We then need to make the goggles enable the dinit script once the package is installed, todo this, create a file called postinst
in the control/
directory of your package and add the following lines to it:
#!/system/bin/sh
/opt/sbin/dinitctl enable hello-world-tune || true
And because we don't want to cause issues if the package is uninstalled, we need to make a file called prerm
in the control/
directory of your package and add the following lines to it:
#!/system/bin/sh
/opt/sbin/dinitctl disable hello-world-tune || true
These files tell dinit to enable the script once the package is installed and disable it before the package is uninstalled.
Step 7: Building the package
Once you're happy with your script you can build the package by running the following command in the root directory of your package:
make
This will create a file called hello-world-tune_1.1.0_pigeon-glasses.ipk
in the ipk
directory of your package, this is the package file that you will install on your goggles.
If you're having issues building your package on windows, you can either push your new package to GitHub, where the worker found in .github/workflows/automation.yml
will build it for you, or you can build it manually by running the following set of commands (using cmd, not powershell) in the root directory of your package:
mkdir ipk
echo "2.0" > ipk/debian-binary
xcopy data ipk\data /E /I
xcopy control ipk\control /E /I
cd ipk\control
tar czvf ..\control.tar.gz .
cd ..\data
tar czvf ..\data.tar.gz .
cd ..
tar czvf ".\hello-word-tune.ipk" .\control.tar.gz .\data.tar.gz .\debian-binary
Step 8: Installing the package
Now that we have the package built we can install it on the goggles, to do this you will need to connect the goggles to your computer via USB and run the following command:
cd ipk
adb push hello-world-tune_1.1.0_pigeon-glasses.ipk /tmp/hello-world-tune_1.1.0_pigeon-glasses.ipk
Once the package is copied to the goggles you will need to access the goggles root shell by running the following command:
adb shell
Once you are in the goggles root shell you can install the package by running the following command:
opkg install /tmp/hello-world-tune_1.1.0_pigeon-glasses.ipk
The package will now be installed on your goggles, to test it you can reboot your goggles and you should hear a little tune play when you power on your goggles!
Step 9: Distributing your package
Now that you have your package built you can distribute the .ipk to your users, if you want your package listed within the fpv.wtf configurator, you will first need to ensure you meet the following requirements:
- The package must be open source
- The package must be licensed under an open source license
- You must manage releases of your package using GitHub releases
- Your releases follow the Semantic Versioning format
- Your package must not start with
wtfos-
as this is reserved for core packages - Your package name must not be tagged with the author/group name.
for exampled3vl-hello-world-tune
is not allowed,hello-world-tune
is allowed
To request your package to be added to the fpv.wtf configurator, you will need to fork the fpv.wtf opkg repository and add your package to the repositories.json
file, you can then create a pull request to have your package added to the fpv.wtf configurator.
For example
{
"repo": "d3vl/wtfos-hello-world-tune",
"names": [ "hello-world-tune" ]
}
You can find the complete source code for this package on our github D3VL/wtfos-hello-world-tune
Congratulations!
You now know how to create a simple package for the fpv.wtf system, if you have any questions or issues, you can find me hanging out on the fpv.wtf discord, tag me @D3VL_Jack
and I'll be happy to help you out!
You can take this package even further and have the goggles (crudely) play a whole song, like this -> youtu.be/Or2vDAn1tqQ, playing pirates of the caribbean - an exercise left to the reader, send in a video if you make any cool tunes!
If you want to see some more examples of packages you can check out Our GitHub.