Skytraxx 3 Hacking Notes
Mục Lục
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: 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.eu/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 <[email protected]>
Date: Wed Jun 6 19:12:59 2018 +0200
adapted toradex dam fix
commit 43f2723ccaee6b44567021f3f0a9b1d04da1bf7f
Author: Juergen <[email protected]>
Date: Thu Oct 5 20:49:19 2017 +0200
dded more wifi stickt to get ieee80211 interface
commit 926b48f14ffd6f2483b73cda20b124769ac55b96
Author: Juergen <[email protected]>
Date: Fri Jun 2 14:50:57 2017 +0200
fsl_lpuart.c synced with toradex-4.4-next
commit 7d41adae92f3029f9cb6590a4b8f8d23e455919a
Author: Juergen <[email protected]>
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/knowledge-base/board-support-package/openembedded-(core)
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 [email protected]:/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/knowledge-base/board-support-package/openembedded-(core) 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 "[email protected]"
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 bluetoothd
service 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
- Bluetooth pairing: http://trac.gateworks.com/wiki/wireless/bluetooth#pairing)
- Bluez4 sample agent: https://git.kernel.org/pub/scm/bluetooth/bluez.git/plain/test/agent.c?h=4.101
- Useful bitbake commands: https://community.nxp.com/docs/DOC-94953
- Skytraxx3 SDK: https://www.skytraxx.eu/skytraxx3/
- Toradex Colibri VFxx Modules: https://www.toradex.com/de/order-now/computer-on-module/colibri-arm-family?q=Colibri+VF
- Skytraxx Linux Kernel: https://github.com/3s1d/linux-toradex
- Bluetooth and Linux: https://www.linux.org/threads/bluetooth-and-linux.4555/