Skip to content

Instantly share code, notes, and snippets.

@nfedera
Last active February 22, 2024 12:01
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nfedera/1702a36909c69e6927aa321fe88e000d to your computer and use it in GitHub Desktop.
Save nfedera/1702a36909c69e6927aa321fe88e000d to your computer and use it in GitHub Desktop.
Skytraxx 3 Hacking Notes

Skytraxx 3 Hacking Notes

Below I've recorded my efforts while trying to analyze and modify the firmware of the amazing Skytraxx 3 flight vario:

Archive of https://www.skytraxx.eu/skytraxx-3

Index

Development VM

Install a new Ubuntu 16.04 VM (I used the server edition) and add the a minimum set of required packages:

sudo apt update
sudo apt upgrade
sudo apt install \
    build-essential \
    python \
    python-setuptools \
    binwalk \
    u-boot-tools \
    bc \
    lzop \
    repo \
    diffstat \
    texi2html \
    texinfo \
    chrpath \
    libsdl1.2-dev
    
mkdir ~/Download/
cd ~/Download/

Download the official Skytraxx cross compiler and toolchain for x64:

wget https://www.skytraxx.org/skytraxx3/angstrom-glibc-x86_64-armv7at2hf-vfp-neon-v2015.06-toolchain.sh
chmod +x angstrom-glibc-x86_64-armv7at2hf-vfp-neon-v2015.06-toolchain.sh
sudo ./angstrom-glibc-x86_64-armv7at2hf-vfp-neon-v2015.06-toolchain.sh

Download Skytraxx 3 Kernel Source:

cd ~/Download/
git clone https://github.com/3s1d/linux-toradex.git
cd linux-toradex
git log
	commit 1549051cc94a19ea0d45db124c2b1a119226f956
	Author: Juergen <juergen@skytraxx.eu>
	Date:   Wed Jun 6 19:12:59 2018 +0200

		adapted toradex dam fix

	commit 43f2723ccaee6b44567021f3f0a9b1d04da1bf7f
	Author: Juergen <juergen@skytraxx.eu>
	Date:   Thu Oct 5 20:49:19 2017 +0200

		dded more wifi stickt to get ieee80211 interface

	commit 926b48f14ffd6f2483b73cda20b124769ac55b96
	Author: Juergen <juergen@skytraxx.eu>
	Date:   Fri Jun 2 14:50:57 2017 +0200

		fsl_lpuart.c synced with toradex-4.4-next

	commit 7d41adae92f3029f9cb6590a4b8f8d23e455919a
	Author: Juergen <juergen@skytraxx.eu>
	Date:   Fri Jun 2 13:19:06 2017 +0200

		fsl_lpuart  bugfxi

Firmware Analysis

Download Skytraxx 3.0 Version 3.0.13c firmware released on July 1, 2019

cd ~/Download/
wget http://www.skytraxx.org/skytraxx3/skytraxx_20190107.siz
file skytraxx_20190107.siz
	skytraxx_20190107.siz: gzip compressed data, last modified: Mon Jan  7 14:47:35 2019, from Unix

mv skytraxx_20190107.siz skytraxx_20190107.tgz
mkdir skytraxx_20190107
cd skytraxx_20190107
tar xvfz ../skytraxx_20190107.tgz
cat app.txt
	13c

cat versions.txt
	Component Versions
	u-boot.imx
	Rootfs skytraxx_VF_V1.0_20170519

cat image.txt
	skytraxx_VF_V1.0_20170519

cat uboot.txt
	2015.04-00052-g0d8a952-dirty

file flash_blk.img
	flash_blk.img: u-boot legacy uImage, Flash Apalis/Colibri module, Linux/PowerPC, Script File (Not compressed), 1655 bytes, Fri May 19 13:41:33 2017, Load Address: 0x00000000, Entry Point: 0x00000000, Header CRC: 0xD277E8E9, Data CRC: 0xEDDA1198

file ubifs.img
	ubifs.img: UBIfs image, sequence number 50492, length 4096, CRC 0x0360f82c

Extract the root fs (ubifs)

cd ~/Download/
git clone https://github.com/jrspruitt/ubi_reader
cd ubi_reader
sudo python setup.py install

cd ~/Download/skytraxx_20190107
ubireader_extract_files ubifs.img
cd ubifs-root/

find .

Check if kernel image has git tag from skytraxx kernel source commits

strings ubifs-root/boot/zImage-4.1 | grep 1549051c
	# nothing
strings ubifs-root/boot/zImage-4.1 | grep g43f2723
	4.1.24-00989-g43f2723-dirty

Perfect, so that was the previous commit which was dirty however.
Probably they did the 1549051c patch first, then build and tested and committed afterwards ;)

cat etc/fstab
	# stock fstab - you probably want to override this with a machine specific one
	/dev/root            /                    auto       defaults              1  1
	proc                 /proc                proc       defaults              0  0
	devpts               /dev/pts             devpts     mode=0620,gid=5       0  0
	usbdevfs             /proc/bus/usb        usbdevfs   noauto                0  0
	tmpfs                /run                 tmpfs      mode=0755,nodev,nosuid,strictatime 0  0
	tmpfs                /var/volatile        tmpfs      defaults              0  0
	/dev/mmcblk0p1 /run/media/mmcblk0p1 auto nofail,auto,noatime,rw 0 2
	/dev/mmcblk0p2 /run/media/mmcblk0p2 auto nofail,auto,noatime,rw,utf8,iocharset=utf8 0 2
	/dev/mmcblk0p3 /run/media/mmcblk0p3 auto nofail,auto,noatime,rw,utf8,iocharset=utf8 0 2
	/run/media/mmcblk0p2/swapfile none swap defaults 0 3

Check which distribution they used

cd ~/Download/skytraxx_20190107/ubifs-root/

cat etc/issue
	The Angstrom Distribution \n \l
	Angstrom v2015.06 - Kernel
	skytraxx_VF_V1.0_20170519

cat etc/angstrom-version
	Angstrom v2015.06 (Core edition)
	Built from branch: (detachedfrom1c916dd)
	Revision: 1c916ddebc3009d3817359144b02745c3ecbd5c4
	Target system: arm-angstrom-linux-gnueabi

cat etc/angstrom-build-info
	Configured Openembedded layers:
	meta-angstrom     = detachedfrom9fb1287:9fb128754a53ce9c8fca1cd332e69518ca805086
	meta-toradex      = V2.5:eb0c16acb10257c60ddbfce8ad71448b2e987fb4
	meta-linaro-toolchain = detachedfromad600ee:ad600ee417d1ff6c266fb9cb7aee32d724533f98
	toolchain-layer
	meta-oe
	meta-efl
	meta-gpe
	meta-gnome
	meta-xfce
	meta-initramfs
	meta-systemd
	meta-networking
	meta-multimedia
	meta-python       = detachedfrom10d3c8f:10d3c8f85280a0bf867a8e4f84bcda81c290d28e
	meta-lxde         = detachedfromb31949a:b31949ae49ae2ede3550c85b80d442a017c85164
	meta-browser      = detachedfrom4b27058:4b27058a8275a5310161459c9bb8f4c52a77762c
	meta-fsl-arm      = detachedfrom44a5115:44a5115b6ece869cfb10714423e6956128dbaef8
	meta-fsl-arm-extra = detachedfrom436b86e:436b86e3421736216412bdbb21cd9cb08c758c75
	meta-fsl-demos    = detachedfrom836bdf5:836bdf5a9d500ed258f1ddc07d89eca74a704098
	meta-skytraxx     = master:ecf730e60c73cbe454e7c25a6fe7d38c3a21c4dc
	meta-filesystems  = detachedfrom10d3c8f:10d3c8f85280a0bf867a8e4f84bcda81c290d28e
	meta              = detachedfrom1c916dd:1c916ddebc3009d3817359144b02745c3ecbd5c4
  • we see an open embedded toradex layer
  • we also see in the info above that this is obviously a toradex colibri vf module
  • Colibri VF50 or Colibri VF61

Lets see if Toradex has any "developer instructions" ... since they have a meta layer I'm pretty confident ...

Yup, this is our starting point: https://developer.toradex.com/linux-bsp/os-development/build-yocto/build-a-reference-image-with-yocto-projectopenembedded

First let's check if we can get a shell into the device.
nmap to the WiFi address of the device shows that ssh is running.

Let's see how ssh is configured:
We can find dropbear in the rootfs and also some authorized ssh keys from the developers.

cat home/root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD5Q/x5KCUH/IFAAUBr7YEhJJ6d8OHl94vmDpen0ew4ppEujYFsX7DZbH2fS9L+QGVcMh/bsk0gyyKWCtzy1y9LeeRRyXy7u7cD4jY4BZvj7GthoJsbchMmTye8Xw/CTCg+qPftZu7lLHEwq0TLpPKwxwLHHvo3UyRPPxSVeCfDl1zWQh3WemDUeuONMl5ln4fMAkmn9qDL1sFEdeY4HjXye6Ytt1iuUy2DYhaWXVaiMznPUP9QXHPdWOKrSXlfLndCgYNcfiO8LLUiFAojKVEiEr0G8JHsBcK1rNy8RtjOMlJxvu+ubUN5PwG8guUOXzIhdoGW/4D8rEzKeUMzffaV sid@ubuntu
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsYPLZOkNQ3ZtAkFvIkZW+OiDs8F/oplmiQsrVlq/kKgTT0Le4RimfExFnsDwCBUT5uHSvnkMs+HRQjFGjHwpf1J+NXwVKETepotwlIRfRzBQCgO6JjCg8mHyMBcpOsgpRcE0fQ16S7Y4b3VP7mxaP+arYkxyaTljPHtFnS5qQLLFZ+EAp5cjxV9g18I62qubf93yLJ5nxBJrjdUpUAQ+uKDejrmSmrpa8TpQyrnDtLBp0TQ6iQImJddZmVDO1NpFH6F8sSiU4YwS84YcVTJSC8D0YHgU2gJ4vRXutzFTAtuDMMLWwkL7yDo89uHaNtT+4pCqjwg1tJY/AFTY8Kjfh michael@Orthos

Note: I've updated the ubifs.img with my own ssh key, recreated the firmware update tgz (.siz) and updated the firmware.

Once in the system I saw that a password was actually set for the root user - contrary to the data in the ubi rootfs image.

Obviously a password is set during firmware update or at runtime.

I've discovered that the device serial number (with leading zeros) is the password of the root user.

That's cool for hacking because one does not have to update the ubifs initially.

On the other hand this is a bit dangerous since 1) the skytraxx serials are sequential and 2) the serials are listed in the igc files, which many users have publicly listed. Knowing this one can ssh into any WiFi connected skytraxx device within seconds.

We can fix this inside ssh:

mount -o remount,rw /
# update your own root password entry in /etc/shadow
# remove or change /home/root/.ssh/authorized_keys
mount -o remount,ro /

When connecting the mini USB to the PC I get an usb network after canceling the skytraxx's connect to pc question.

On the skytraxx side this device always has the ip 192.168.11.1 and does not request a DHCP address.

So I configure the usb ethernet interface on my host to 192.168.11.123 which is of course the preferred way to work with the device, especially when testing WiFi adapters ;)

Basic Firmware Modifications

The Skytraxx3 comes with an 8 GB SD card which has three partitions:

fdisk -l /dev/mmcblk0

Disk /dev/mmcblk0: 7994 MB, 7994343424 bytes
4 heads, 16 sectors/track, 243968 cylinders
Units = cylinders of 64 * 512 = 32768 bytes

		Device Boot      Start         End      Blocks  Id System
/dev/mmcblk0p1              33        8224      262144   6 FAT16
/dev/mmcblk0p2            8225       40992     1048576   b Win95 FAT32
/dev/mmcblk0p3           40993      243968     6495232   b Win95 FAT32

mount | grep mmcblk
/dev/mmcblk0p1 on /run/media/mmcblk0p1 type vfat (rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
/dev/mmcblk0p2 on /run/media/mmcblk0p2 type vfat (rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=utf8,shortname=mixed,utf8,errors=remount-ro)
/dev/mmcblk0p3 on /run/media/mmcblk0p3 type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

df -h | grep mmcblk
Filesystem                Size      Used Available Use% Mounted on
/dev/mmcblk0p1          255.7M     60.4M    195.4M  24% /run/media/mmcblk0p1
/dev/mmcblk0p2         1022.0M    348.4M    673.5M  34% /run/media/mmcblk0p2
/dev/mmcblk0p3            6.2G      1.7G      4.4G  28% /run/media/mmcblk0p3
  • mmcblk0p1 seems to be used for firmware updates
  • mmcblk0p2 is used to store non-volatile system data (WiFi/connman config, all your Skytraxx settings, the uncompressed current active map, etc.)
  • mmcblk0p3 holds the data you see when connection the Skytraxx3 to your computer

Since the ubifs root filesystem is mounted read-only and /dev/mmcblk0p3 will get unmounted if you connect the device to the PC, I will use a subdirectory hacks under /run/media/mmcblk0p2/ for storing any added binaries/configs/modifications. This should also minimize required changes to the rootfs after a firmware update. For convenience I will create a rootfs link /hacks to this directory:

mkdir /run/media/mmcblk0p2/hacks
mount -o remount,rw /
ln -s /run/media/mmcblk0p2/hacks /hacks
mount -o remount,ro /

Add some subfolders to keep it organized:

mkdir /hacks/cfg
mkdir /hacks/bin
mkdir /hacks/modules

Start with some modifications:

# mount rootfs rw
mount -o remount,rw /

# permanent bash history
ln -s /hacks/cfg/.bash_history ~/.bash_history

# vim stuff
touch /hacks/cfg/.viminfo
cat <<EOT >/hacks/cfg/.vimrc
set viminfo=%,<800,'10,/50,:100,h,f0,n/hacks/cfg/.viminfo
set undodir=/tmp
set noincsearch
set nobackup
set nowritebackup
set mouse-=a
set wrap!
set background=dark
EOT
ln -s /hacks/cfg/.vimrc ~/.vimrc

# ssh authorized keys file
cd ~/.ssh
mv authorized_keys /hacks/cfg/authorized_keys
ln -s /hacks/cfg/authorized_keys ~/.ssh/authorized_keys

# mount rootfs ro
mount -o remount,ro /

Now back to the firmware:

For whatever modifications and changes we'd like to do in the future we want to create or modify our own openembedded packages.

And we want to add kernel modules for non supported usb hardware.

Kernel Compilation

Inside ssh we verify the information we've previously extracted offline from the rootfs image

uname -a
	Linux skytraxx-vf 4.1.24-00989-g43f2723-dirty #33 Wed Jun 6 17:22:17 CEST 2018 armv7l GNU/Linux

dmesg
	[    0.000000] Booting Linux on physical CPU 0x0
	[    0.000000] Linux version 4.1.24-00989-g43f2723-dirty (sid@ubuntu) (gcc version 4.9.3 20150311 (prerelease) (Linaro GCC 4.9-2015.03) ) #33 Wed Jun 6 17:22:17 CEST 2018
	[    0.000000] CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c5387d
	[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
	[    0.000000] Machine model: Toradex Colibri VF50 on Skytraxx Board
	...
	[    0.963534] Hardware name: Freescale Vybrid VF5xx/VF6xx (Device Tree)
	...
	[   14.798431] FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
	[   15.947068] FAT-fs (mmcblk0p2): utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive!
	[   16.007732] FAT-fs (mmcblk0p2): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.

Kernel version matches, but dmesg says it is a Colibri VF50 and not a VF61 ... we'll see if that really matters at all.

See if the compiler matches the compiler from the Skytraxx SDK:

/usr/local/oecore-x86_64/sysroots/x86_64-angstromsdk-linux/usr/bin/arm-angstrom-linux-gnueabi/arm-angstrom-linux-gnueabi-gcc --version
	arm-angstrom-linux-gnueabi-gcc (Linaro GCC 4.9-2015.03) 4.9.3 20150311 (prerelease)

Perfect! Let's try to compile that kernel:

First source the sdk environment setup

. /usr/local/oecore-x86_64/environment-setup-armv7at2hf-vfp-neon-angstrom-linux-gnueabi

Run ${CC} --version for verification.

cd ~/Download/linux-toradex/

Get the config from the running device and see if it matches the .config from the linux source

scp root@192.168.11.1:/proc/config.gz .
zcat config.gz >config-skytraxx
diff -u config-skytraxx .config
	# no differences

Cool, the .config in git is up2date.

In order to get the exact same kernel version (g43f2723-dirty) I first check out the 43f2723 commit and manually apply the patch to the current commit

git diff 43f2723 >tmp.diff
git checkout -b skytraxx-g43f2723-dirty 43f2723
patch -p1 < tmp.diff
git diff skytraxx_vf_4.1-next
# last command should not show any differences

make zImage LD=${CROSS_COMPILE}ld.bfd
#           ^^ that LD option is the recommended solution if you get
#           a "--pic-veneer: unknown option" error

mkdir modules
make modules
make modules_install INSTALL_MOD_PATH=modules

That worked perfectly fine for me, so all prepared for adding any missing kernel/driver functionality in the future.

Open Embedded Build

Now we setup the openembedded distribution from Toradex

Read all of https://developer.toradex.com/linux-bsp/os-development/build-yocto/build-a-reference-image-with-yocto-projectopenembedded/ first to get an overview!

Lets try to find out which Version was used by the Skytraxx developers:

In the root fs image we found the following infos:

  • Angstrom v2015.06 - Kernel
  • skytraxx_VF_V1.0_20170519
  • Angstrom v2015.06 (Core edition)
  • Built from branch: (detached from 1c916dd)
  • Revision: 1c916ddebc3009d3817359144b02745c3ecbd5c4
  • Target system: arm-angstrom-linux-gnueabi

This matches the following row data in the table on top of that toradex web page

Toradex Version 2.5
Ångström v2015.06
OpenEmbedded/Yocto Codename: fido
Yocto Project Release 1.8

Now we need to find out which branch in the toradex-bsp-platform.git we have to use

We analyze http://git.toradex.com/cgit/meta-toradex.git/ and http://git.toradex.com/cgit/toradex-bsp-platform.git/

According to our etc/angstrom-build-info in the rootfs image we have:

Configured Openembedded layers:
meta-toradex      = V2.5:eb0c16acb10257c60ddbfce8ad71448b2e987fb4

We find that commit here:
http://git.toradex.com/cgit/meta-toradex.git/commit/?id=eb0c16acb10257c60ddbfce8ad71448b2e987fb4

And that commit is tagged with "Colibri_VF_LinuxImageV2.5Beta1_20150813"

With this information we can find the correct object in the toradex-bsp-platform.git:
http://git.toradex.com/cgit/toradex-bsp-platform.git/tree/?h=Colibri_VF_LinuxImageV2.5Beta1_20150813

And we can verify that the default.xml ...
http://git.toradex.com/cgit/toradex-bsp-platform.git/tree/default.xml?h=Colibri_VF_LinuxImageV2.5Beta1_20150813
... references commit eb0c16acb10257c60ddbfce8ad71448b2e987fb4 from "meta-toradex.git"

Note: I use a new shell to make sure that the environment is clear from the /usr/local/oecore-x86_64/ SDK

git config --global user.name "Skytraxx Hacker"
git config --global user.email "hacker@skytraxxdev.local"

mkdir ~/oe-core/
cd ~/oe-core/

We could use the same exact tag used by Skytraxx initially ...

# repo init -u http://git.toradex.com/toradex-bsp-platform.git -b refs/tags/Colibri_VF_LinuxImageV2.5Beta1_20150813

... but chances are high that many source links became invalid meanwhile, so lets stick to the hopefully still maintained LinuxImageV2.5 branch:

repo init -u http://git.toradex.com/toradex-bsp-platform.git -b LinuxImageV2.5
#	repo has been initialized in /home/ubuntu/oe-core
repo sync

Source the file 'export' to setup the environment:
On first invocation, this also copies a sample configuration to build/conf/*.conf.

. export

Note: Sourcing export configures the shell environment for the current shell session. It must be entered whenever a new shell session is opened for use with OpenEmbedded.

Edit conf/local.conf , find MACHINE ?= "colibri-t20" and replace it with:

MACHINE ?= "colibri-vf"

We should be done, test some bitbake commands:

Show layers:

bitbake-layers show-layers

Show available recipes:

bitbake-layers show-recipes

And now can build our first packages

Let's build a webserver with php and also vim for my convenience:

bitbake lighttpd
bitbake php
bitbake vim

The first bake might take a really long time.
The more packages we build the faster it gets because more and more dependencies will be in place.

You can find the produced packages under ~/oe-core/build/out-glibc/deploy/ipk/

FIXME: Describe how I've installed the packages on the skytraxx 3 !!

Project 1: Support "2 in 1" WiFi/Bluetooth Nano USB Stick

Product: Edimax EW-7611ULB 2- in 1 Wireless & Bluetooth nano USB Adapter.

Amazon Link: https://www.amazon.de/dp/B01INRAC2C

USB Info: lsusb Bus 001 Device 002: ID 7392:a611 Edimax Technology Co., Ltd lsusb -v -d 7392:a611

Recompile kernel modules with bluetooth first:

First start a new shell, source the official SDK, then:

cd ~/Download/linux-toradex/

Append the following to .config

CONFIG_BT=m
CONFIG_BT_BREDR=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
CONFIG_BT_LE=y
CONFIG_BT_SELFTEST=n
CONFIG_BT_DEBUGFS=n
CONFIG_BT_INTEL=m
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTUSB_BCM=y
CONFIG_BT_HCIBTSDIO=n
CONFIG_BT_HCIUART=n
CONFIG_BT_HCIBCM203X=n
CONFIG_BT_HCIBPA10X=n
CONFIG_BT_HCIBFUSB=n
CONFIG_BT_HCIVHCI=n
CONFIG_BT_MRVL=n
CONFIG_BT_ATH3K=n

Rebuild the modules:

make modules

Now collect the following .ko files and transfer them to /hacks/modules/ on the skytraxx3

kernel/net/bluetooth/bluetooth.ko
kernel/net/bluetooth/bnep/bnep.ko
kernel/net/bluetooth/rfcomm/rfcomm.ko
kernel/net/bluetooth/hidp/hidp.ko

kernel/drivers/bluetooth/btbcm.ko
kernel/drivers/bluetooth/btintel.ko
kernel/drivers/bluetooth/btusb.ko

Edimax EW-7611ULB WiFi Driver:

Unfortunately this driver is not in the mainstream kernel but thanks to Larry Finger we are not left out in the rain: https://github.com/lwfinger/

The WIFI driver is in this repo: https://github.com/lwfinger/rtl8723bu

cd ~/Download/
git clone https://github.com/lwfinger/rtl8723bu.git
cd rtl8723bu/

In Makefile disable/comment EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE then:

. /usr/local/oecore-x86_64/environment-setup-armv7at2hf-vfp-neon-angstrom-linux-gnueabi

export MYKERNELDIR=~/Download/linux-toradex
make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C ${MYKERNELDIR} M=$(pwd) modules
  • Transfer 8723bu.ko to /hacks/modules/ on the Skytraxx3
  • Transfer rtl8723b_fw.bin to /hacks/modules/firmware/rtl_bt/ on the Skytraxx3, it will be required later for the bluetooth driver

Edimax EW-7611ULB Bluetooth Driver:

We need to apply a little patch to the USB bluetooth driver in the skytraxx kernel source:

First apply the following patch to `~/Download/linux-toradex/``

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index ac553f9..5bc74f0 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -67,6 +67,9 @@ static const struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth AMP device */
 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP },
	
+	/* Generic Bluetooth USB interface */
+	{ USB_INTERFACE_INFO(0xe0, 0x01, 0x01) },
+
 	/* Apple-specific (Broadcom) devices */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01),
 	  .driver_info = BTUSB_BCM_APPLE },
@@ -152,6 +155,10 @@ static const struct usb_device_id btusb_table[] = {
 	{ USB_DEVICE(0x8087, 0x0a5a),
 	  .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
	  
+	/* Realtek Bluetooth devices */
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
+	  .driver_info = BTUSB_REALTEK },
+
 	{ }	/* Terminating entry */
 };
 
@@ -328,6 +335,9 @@ static const struct usb_device_id blacklist_table[] = {
 	{ USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
 	{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
	
+	/* Additional Realtek 8723BU Bluetooth devices */
+	{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
+
 	{ }	/* Terminating entry */
 };

Now recompile the kernel modules ...

. /usr/local/oecore-x86_64/environment-setup-armv7at2hf-vfp-neon-angstrom-linux-gnueabi
cd ~/Download/linux-toradex/
make modules
make modules_install INSTALL_MOD_PATH=modules

... and copy the updated btusb.ko to /hacks/modules/ on the Skytraxx3.

Bluetooth Service State Directory

The Bluetooth service stores all data (pairing info etc.) under /var/lib/bluetooth/ .
On the Skytraxx3 this directory is only in RAM and will be lost after you reboot your Skytraxx.

Unfortunately we cannot simply link this directory to e.g. /hacks/cfg because the vfat filesystem does not support certain characters used by bluetoothd.

My workaround is to tell systemd to automatically extract this directory's contents from /hacks/cfg/bluetooth.tar before bluetooth is started and to update this archive when the service is stopped:

Create the file /etc/systemd/system/bluetooth.service.d/extstorage.conf with the following content:

[Service]
ExecStartPre=-/bin/tar -x -f /hacks/cfg/bluetooth.tar -C /var/lib/
ExecStop=/bin/tar -c -f /hacks/cfg/bluetooth.tar -C /var/lib bluetooth

Note: You need to make the rootfs writable first via mount -o remount,rw / and don't forget to immediately make it read-only after you've created that file: mount -o remount,ro /

Edimax Bluetooth+WiFi Setup Script

Create the directory app under Skytraxx's sdcard mount point:

mkdir /run/media/mmcblk0p3/app

Note: Programs/Scripts in this directory can conveniently be launched directly from the Skytraxx3 App (Menu Programs -> External Programs)

Inside this directory create the following shell script and call it e.g. enable_edimax.app

#/bin/bash

DRIVERS="/hacks/modules"

systemctl stop bluetooth

#### set firmware search path
echo -n "$DRIVERS/firmware" > /sys/module/firmware_class/parameters/path

#### Wifi+Bluetooth Edimax N150 EW-7611ULB

# WiFi
echo "Inserting WiFi modules"
modprobe cfg80211
insmod "$DRIVERS/8723bu.ko"

# Bluetooth
echo "inserting bluetooth modules"
insmod "$DRIVERS/bluetooth.ko"
insmod "$DRIVERS/bnep.ko"
insmod "$DRIVERS/hidp.ko"
insmod "$DRIVERS/rfcomm.ko"
insmod "$DRIVERS/btbcm.ko"
insmod "$DRIVERS/btintel.ko"
insmod "$DRIVERS/btusb.ko"

echo "Unblocking bluetooth radio"
rfkill unblock bluetooth
#rfkill list all

echo "Starting bluetooth service"
systemctl start bluetooth

After you run this script, WiFi should already be working - until reboot of course ;)

You should also confirm that the bluetooth interface is up and running now:

Running hciconfig should display something like this:

root@skytraxx-vf: hciconfig
hci0:  Type: BR/EDR  Bus: USB
BD Address: 08:BE:AC:11:22:33  ACL MTU: 820:8  SCO MTU: 255:16
UP RUNNING PSCAN
RX bytes:1273 acl:0 sco:0 events:130 errors:0
TX bytes:23814 acl:0 sco:0 commands:130 errors:0

You should also be able to scan for nearby visible bluetooth devices using the command hcitool scan on the Skytraxx3:

root@skytraxx-vf:~# hcitool scan
Scanning ...
        E1:23:18:12:34:56  Bluetooth 3.0 Keyboard
        C4:9F:4C:12:34:56  Huawei P20 Pro
        00:13:43:12:34:56  SkyDrop SPP
        00:21:3E:12:34:56  TomTom Remote
        0C:FC:83:12:34:56  AB Shutter 3

Bluetooth Pairing

Skytraxx already has installed the Bluez4 service daemon and control binaries.

However, there are no pairing utilities and lots of manual d-bus actions are required for the initial setup.
Since pairing on the command line is a PITA anyways, you should first read http://trac.gateworks.com/wiki/wireless/bluetooth#pairing first to get familiar with the topic.

First we need to compile a simple native pairing agent for the Skytraxx.

We will take agent.c from the bluez4 testing tools:

cd ~/Download/
mkdir tools
cd tools
wget -O agent.c "https://git.kernel.org/pub/scm/bluetooth/bluez.git/plain/test/agent.c?h=4.101"

. /usr/local/oecore-x86_64/environment-setup-armv7at2hf-vfp-neon-angstrom-linux-gnueabi

${CC} -DVERSION=4.101 agent.c `pkg-config --cflags --libs dbus-1` -o agent

Now transfer the agent binary to /hacks/bin/ on your Skytraxx3.

Example for pairing a Bluetooth keyboard:

1.) Prepare any Bluetooth Keyboard and put it in pairing mode.

2.) Run hcitool scan on the Skytraxx3

root@skytraxx-vf:~# hcitool scan
Scanning ...
        E1:23:18:12:34:56  Bluetooth 3.0 Keyboard

Note the address in two formats, with : and with _:

export BTDEV_A=E1:23:18:12:34:56
export BTDEV_B=E1_23_18_12_34_56

3.) Pair the device using our compiled agent binary using the pin 0000

/hacks/bin/agent 0000 $BTDEV_A

4.) Verify via the bluetoothd's d-bus api that the device is present

export BTADAPTER=`dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.DefaultAdapter | tail -1 | sed 's/^.*"\(.*\)".*$/\1/'`
dbus-send --system --dest=org.bluez --print-reply $BTADAPTER org.bluez.Adapter.ListDevices

This should now list our keyboard: method return sender=:1.8 -> dest=:1.17 reply_serial=2 array [ object path "/org/bluez/1483/hci0/dev_E1_23_18_12_34_56" ]

5.) Set the device as Trusted

export BTADAPTER=`dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.DefaultAdapter | tail -1 | sed 's/^.*"\(.*\)".*$/\1/'`
dbus-send --system --dest=org.bluez --print-reply $BTADAPTER/dev_$BTDEV_B org.bluez.Device.SetProperty string:Trusted variant:boolean:true

6.) Now you should be able to operate your Skytraxx3 using your Bluetooth keyboard.

The four buttons on the Skytraxx3 from left to right are: Escape, Up, Down, Enter

If it is not working you can try restarting the bluetooth service via systemctl restart bluetooth.
Also check the output of dmesg.

For debugging it is also helping to run the bluetoothdservice in an extra terminal with debug output in foreground and watch for errors and messages:

systemctl stop bluetooth
bluetoothd -d -n

Bluetooth helper script

I've created a simple shell script that mostly prevents having to enter the low level commands above for listing and pairing:

cd ~/Downloads
wget -O bluetooth "https://gist.githubusercontent.com/nfedera/3a2cc4677647c9c3b4c8ffd7f29ecc7b/raw"

Now transfer the downloaded script bluetooth to /hacks/bin/ on your Skytraxx3.

usage: /hacks/bin/bluetooth [scan|list|names|trusts|props|remove|pair|ping]

Remapping Bluetooth HID Keyboard Keys

I want to map the buttons of my Bluetooth input devices to specific functions of the Skytraxx3 flight app.

The Skytraxx3 App supports the following keys using a normal USB keyboard:

HID KEY         | Function
----------------+----------------------------------------------
KEY_ESC         | Like the 1st hardware key (menu/back)
KEY_UP          | Like the 2nd hardware key (up/zoom/volume)
KEY_DOWN        | Like the 3rd hardware key (down/zoom/volume)
KEY_ENTER       | Like the 4th hardware key (ok/enter)
KEY_VOLUMEUP    | Volume up
KEY_VOLUMEDOWN  | Volume down
KEY_TAB         | Screenshot
KEY_F1          | Zoom in
KEY_F2          | Zoom out
KEY_F3          | Next flight screen
KEY_F4          | Previous flight screen
KEY_F5          | Next Turn Point
KEY_F6          | Previous Turn Point

Since you cannot control which key is sent by a bluetooth device we have to remap the keys on the linux side.

For that you need to compile my quick and dirty key remapper:

cd ~/Download/tools
wget -O remap.c "https://gist.githubusercontent.com/nfedera/03cf3e0b69eaeef5971e1d4dc3010f12/raw"
. /usr/local/oecore-x86_64/environment-setup-armv7at2hf-vfp-neon-angstrom-linux-gnueabi
${CC} remap.c -o remap

Now transfer the remap binary to /hacks/bin/ on your Skytraxx3.

Example: Remapping the keys of my TomTom Bluetooth Remote

I want to control my Skytraxx3 flight app with my TomTom Remote: This one: https://www.amazon.de/dp/B00CGYE86A

This device has 10 buttons:

  • a 5-button jog (left, right, up, down, ok) on top
  • three little knob-like buttons in the center
  • a volume control (up/down).

The first thing to do is recording the scancodes produced by each button using evtest:

root@skytraxx-vf:~# evtest --grab /dev/input/event0
Input driver version is 1.0.1
Input device ID: bus 0x5 vendor 0x0 product 0x0 version 0x0
Input device name: "TomTom Remote"

# pressing "jog left"
Event: time 1567085581.297377, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70050
# pressing "jog right"
Event: time 1567085581.892333, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7004f
# pressing "jog up"
Event: time 1567085583.422649, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70052
# pressing "jog down"
Event: time 1567085583.947529, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70051
# pressing "jog ok"
Event: time 1567085585.238536, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
# pressing "knob left"
Event: time 1567085587.065062, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70029
# pressing "knob middle"
Event: time 1567085587.518814, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7002e
# pressing "knob right"
Event: time 1567085587.885058, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7002a
# pressing "volume minus"
Event: time 1567085588.513152, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70042
# pressing "volume right"
Event: time 1567085589.036063, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70043

In order to assign these scancodes to the functions of my liking, I run the following remap commands:

DEVNAME=/dev/input/event0
/hacks/bin/remap $DEVNAME 70042 KEY_VOLUMEDOWN
/hacks/bin/remap $DEVNAME 70043 KEY_VOLUMEUP
/hacks/bin/remap $DEVNAME 70028 KEY_ENTER        # jog ok      -> ok/enter
/hacks/bin/remap $DEVNAME 70052 KEY_UP           # jog up      -> arrow up
/hacks/bin/remap $DEVNAME 70051 KEY_DOWN         # jog down    -> arrow down
/hacks/bin/remap $DEVNAME 70050 KEY_F4           # jog left    -> prev flightscreen
/hacks/bin/remap $DEVNAME 7004f KEY_F3           # jog right   -> next flightscreen
/hacks/bin/remap $DEVNAME 70029 KEY_ESC          # knob left   -> menu
/hacks/bin/remap $DEVNAME 7002e KEY_F1           # knob middle -> zoom in
/hacks/bin/remap $DEVNAME 7002a KEY_F2           # knob right  -> zoom out

These remappings are not permanent. Thus I will create a udev rule to run a remapping script when an input device is connected:

Create the file /etc/udev/rules.d/90-input.rules with the following content:

SUBSYSTEM=="input", KERNELS=="input*", ACTION=="add", ENV{MY_UNIQ}="$attr{uniq}", ENV{MY_NAME}="$attr{name}", RUN+="/hacks/bin/udev_input_added.sh"

Note: You need to make the rootfs writable first via mount -o remount,rw / and don't forget to immediately make it read-only after you've created that file: mount -o remount,ro /

As you can see this rule will set two environment variables:

  • MY_UNIQ contains the hardware address (e.g. 11:22:33:44:55)
  • MY_NAME contains the name of the added input device (e.g. "TomTom Remote")

This allows the /hacks/bin/udev_input_added.sh script to do the correct mappings for different remotes and to to do different mappings for multiple remotes of the same type (e.g. if you have two selfie buttons).

Here is a copy of the /hacks/bin/udev_input_added.sh script I'm using:

#!/bin/bash

# My Selfie Button 1 "AB Shutter 3" used to switch flight screens
if [ "$MY_UNIQ" = "0c:fc:83:11:22:33" ]; then
	/hacks/bin/remap $DEVNAME c00e9 KEY_F4
	/hacks/bin/remap $DEVNAME 70028 KEY_F3
	exit 0
fi

# My Selfie Button 2 "AB Shutter 3" used for zoom
if [ "$MY_UNIQ" = "0c:fc:83:22:33:44" ]; then
	/hacks/bin/remap $DEVNAME c00e9 KEY_F1
	/hacks/bin/remap $DEVNAME 70028 KEY_F2
	exit 0
fi

# My TomTom Remote
if [ "$MY_NAME" = "TomTom Remote" ]; then
	/hacks/bin/remap $DEVNAME 70042 KEY_VOLUMEDOWN
	/hacks/bin/remap $DEVNAME 70043 KEY_VOLUMEUP
	/hacks/bin/remap $DEVNAME 70028 KEY_ENTER       # jog ok      -> ok/enter
	/hacks/bin/remap $DEVNAME 70052 KEY_UP          # jog up      -> arrow up
	/hacks/bin/remap $DEVNAME 70051 KEY_DOWN        # jog down    -> arrow down
	/hacks/bin/remap $DEVNAME 70050 KEY_F4          # jog left    -> prev flightscreen
	/hacks/bin/remap $DEVNAME 7004f KEY_F3          # jog right   -> next flightscreen
	/hacks/bin/remap $DEVNAME 70029 KEY_ESC         # knob left   -> menu
	/hacks/bin/remap $DEVNAME 7002e KEY_F1          # knob middle -> zoom in
	/hacks/bin/remap $DEVNAME 7002a KEY_F2          # knob right  -> zoom out
	 exit 0
fi

Video demo: https://youtu.be/AV0gZF0lzcw

Bluetooth Network/Internet Access via a Smartphones Bluetooth Tethering (PAN)

The connman version on the Skytraxx3 is 1.32, which has no more support for bluez4 (the current bluetooth stack on the Skytraxx3).
This is the connman commit that removed bluez4 support:
https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=9df6584563c8343b2d06e2a4117644766046183d

My plan is to rebuild connmand with legacy (bluez4) support by reverting that commit.

First issue is the Ångström openembedded distribution I've used has connman version 1.28.
Second issue is that Skytraxx has made some changes to connman.

So first thing is replacing ~/oe-core/stuff/openembedded-core/meta/recipes-connectivity/connman/ directory with the upstream 1.32 version:

Under http://git.openembedded.org/openembedded-core/log/meta/recipes-connectivity/connman I've looked for the commit that added connman 1.32.

I've selected openembedded-core commit 708cd88608d2407db3d679cb6489dcdad58af5b7 which seems to include some additional fixes after the connman-1.32 upgrade, downloaded a snapshot and simply took the connman folder from that archive:

wget "http://git.openembedded.org/openembedded-core/snapshot/openembedded-core-708cd88608d2407db3d679cb6489dcdad58af5b7.tar.gz"
# replace our recipes-connectivity/connman/ contents with that from the downloaded tar ball

Next I generated the reverse patch from that commit which had removed bluez4 support from connman and added it to the package build:

cd ~/Download/
git clone git://git.kernel.org/pub/scm/network/connman/connman.git
cd connman
git show -R 9df6584563c8343b2d06e2a4117644766046183d >/tmp/0009-resurrect-bluez4.patch
mv /tmp/0009-resurrect-bluez4.patch ~/oe-core/stuff/openembedded-core/meta/recipes-connectivity/connman/connman/

We also have to reference this patch file in our connman_1.32.bb by adding the following line:

SRC_URI_append = "file://0009-resurrect-bluez4.patch"

Finally we need the changes made by Skytraxx.

The only change they made to connman was setting the local statedir to /run/media/mmcblk0p2:

Thus we add ...

CONFIGUREOPTS := "${@d.getVar('CONFIGUREOPTS', True).replace('--localstatedir=${localstatedir}', '--localstatedir=/run/media/mmcblk0p2')}"

... to our ~/oe-core/stuff/openembedded-core/meta/recipes-connectivity/connman/connman_1.32.bb

I also had to remove the item file://dont_start_connman_on_nfsboot.patch from the SRC_URI array of ~/oe-core/stuff/meta-toradex/recipes-connectivity/connman/connman_%.bbappend

Now we can rebuild the connman package.

Start a new shell and:

cd ~/oe-core
. export	
bitbake -c cleansstate connman
bitbake connman
exit

I've extracted the usr/sbin/connmand binary from the generated .ipk package and copied it to /tmp/ on the Skytraxx and replaced the existing /usr/sbin/connmand executable:

systemctl stop connman
mount -o remount,rw /
mv /usr/sbin/connmand /usr/sbin/connmand.orig
mv /tmp/connmand /usr/sbin/connmand
mount -o remount,ro /
systemctl start connman

At this point you should have activated Bluetooth-Tethering on your phone and completed the pairing process!

Now connmanctl should display the automatically detected bluetooth pan service of the paired phone:

root@skytraxx-vf:~# connmanctl services
*   Huawei P20 Pro             bluetooth_08beac112233_c49f4c112233

If you wonder what the characters mean:
The connman service naming scheme is bluetooth_hostMacAddress_targetMacAddress

Time to connect to the internet:

root@skytraxx-vf:~# connmanctl connect bluetooth_08beac112233_c49f4c112233
Connected bluetooth_08beac112233_c49f4c112233

root@skytraxx-vf:~# ifconfig bnep0
bnep0     Link encap:Ethernet  HWaddr 08:BE:AC:11:22:33
          inet addr:192.168.44.151  Bcast:192.168.44.255  Mask:255.255.255.0

root@skytraxx-vf:~# connmanctl state
  State = online
  OfflineMode = False
  SessionMode = False

Speed is a bit less than 2 MBit/s, good enough for geo data updates and igc uploads but too slow for downloading maps ;)

Fixme: Describe how auto connect works.

Project 2: USB Tethering

Goal: Provide internet connection to the Skytraxx 3 via an USB-connected (host port) Android Phone.
Unfortunately the Skytraxx 3 OS is missing the required rndis_host.ko kernel module, so let's build it:

First start a new shell and source the sdk environment setup

. /usr/local/oecore-x86_64/environment-setup-armv7at2hf-vfp-neon-angstrom-linux-gnueabi

Change to the kernel source directory:

cd ~/Download/linux-toradex/

Append the following to .config

CONFIG_USB_NET_RNDIS_HOST=m

Rebuild the modules:

make modules

Now collect the following .ko files and transfer them to /hacks/modules/ on the skytraxx3

kernel/drivers/net/usb/rndis_host.ko
kernel/drivers/net/usb/cdc_ether.ko

On the Skytraxx:

modprobe usbnet
insmod /hacks/modules/cdc_ether.ko
insmod /hacks/modules/rndis_host.ko

In /etc/connman/main.conf find the line starting with NetworkInterfaceBlacklist and change the string usb to usb0.

Restart connman and run:

connmanctl enable ethernet

That's it. Connect the Android Phone, enable USB Tethering and the Skytraxx should have an internt connection.

Unwanted charging:
Now if you connect the Android phone to the Skytraxx's Host USB port the phone will immediately start draining power.
This might be awsome if you have connected a powerbank, if not it will drain the Skytraxx's battery - I've measured 500mA.
My simple hack was adding a 100 ohm resistor in series with the 5V line (red wire) of the USB cable which reduced the current from the Skytraxx to about 5mA.

FIXME: Describe how to make this feature permanent.

What about iPhone/IOS ?

TODO. As usual this requires more work. We probably have to add the ipheth.ko kernel module and the usbmuxd package for this.

Links

@sepi
Copy link

sepi commented Oct 5, 2023

This is amazing information but unfortunately the SDK is not available anymore. Do you know if I could just build the toolchain differently?

@nfedera
Copy link
Author

nfedera commented Feb 16, 2024

@sepi I've updated all stale links

@BitBrokerEU
Copy link

@nfedera
Ist es möglich - auf einfache Weise - Keys zu mappen?
Ich habe ein 2,4G Keyboard welches KEY_RETURN (NumPad) statt KEY_ENTER sendet und das wird leider nicht verarbeitet. Was muss/kann ich modifizieren?

@nfedera
Copy link
Author

nfedera commented Feb 22, 2024

@nfedera Ist es möglich - auf einfache Weise - Keys zu mappen? Ich habe ein 2,4G Keyboard welches KEY_RETURN (NumPad) statt KEY_ENTER sendet und das wird leider nicht verarbeitet. Was muss/kann ich modifizieren?

Ja sicher, zuerst via evtest --grab /dev/input/event0 (falls event0 dein keyboard ist) den MSC_SCAN value ermitteln.
Bei meinem USB Keyboard wäre das der Value 70058.
Dann diesen scan code via /hacks/bin/remap /dev/input0 70058 KEY_ENTER auf KEY_ENTER mappen.

Also genau wie unter Remapping Bluetooth HID Keyboard Keys beschrieben.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment