diff --git a/external/cache/debs/aptly/aptly_1.4.0+44+g24a0271_amd64.deb b/external/cache/debs/aptly/aptly_1.4.0+44+g24a0271_amd64.deb
new file mode 100644
index 0000000..09d3660
Binary files /dev/null and b/external/cache/debs/aptly/aptly_1.4.0+44+g24a0271_amd64.deb differ
diff --git a/external/cache/debs/arm64/.gitignore b/external/cache/debs/arm64/.gitignore
new file mode 100644
index 0000000..3249e43
--- /dev/null
+++ b/external/cache/debs/arm64/.gitignore
@@ -0,0 +1,3 @@
+chromium-browser*
+chromium-codecs-ffmpeg-extra*
+firefox-esr*
diff --git a/external/cache/debs/arm64/layout_switcher/layoutswitcher_0.2-0_all.deb b/external/cache/debs/arm64/layout_switcher/layoutswitcher_0.2-0_all.deb
new file mode 100644
index 0000000..b56d585
Binary files /dev/null and b/external/cache/debs/arm64/layout_switcher/layoutswitcher_0.2-0_all.deb differ
diff --git a/external/cache/debs/arm64/usbmount_0.0.24_all.deb b/external/cache/debs/arm64/usbmount_0.0.24_all.deb
new file mode 100644
index 0000000..9202f58
Binary files /dev/null and b/external/cache/debs/arm64/usbmount_0.0.24_all.deb differ
diff --git a/external/cache/debs/arm64/wiringpi_2.51.deb b/external/cache/debs/arm64/wiringpi_2.51.deb
new file mode 100644
index 0000000..12c618c
Binary files /dev/null and b/external/cache/debs/arm64/wiringpi_2.51.deb differ
diff --git a/external/cache/debs/extra/bionic-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..a70d139
Binary files /dev/null and b/external/cache/debs/extra/bionic-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..865bc7d
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..1aaeebb
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..8013ea5
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..47dc242
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..612ba7d
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..2a9b5e7
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..7f73e7d
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..220ab25
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bookworm-desktop/null.txt b/external/cache/debs/extra/bookworm-desktop/null.txt
new file mode 100644
index 0000000..e69de29
diff --git a/external/cache/debs/extra/bookworm-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb b/external/cache/debs/extra/bookworm-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb
new file mode 100644
index 0000000..51cf71b
Binary files /dev/null and b/external/cache/debs/extra/bookworm-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx-common_1.0~beta+git20210222-1~ppa1_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx-common_1.0~beta+git20210222-1~ppa1_all.deb
new file mode 100755
index 0000000..39c46d1
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx-common_1.0~beta+git20210222-1~ppa1_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx-dockx_1.0~beta+git20210222-1~ppa1_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx-dockx_1.0~beta+git20210222-1~ppa1_all.deb
new file mode 100755
index 0000000..1cf2085
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx-dockx_1.0~beta+git20210222-1~ppa1_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx-theme-zorin_1.1.0_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx-theme-zorin_1.1.0_all.deb
new file mode 100755
index 0000000..4269807
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx-theme-zorin_1.1.0_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx_1.0~beta+git20210222-1~ppa1_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx_1.0~beta+git20210222-1~ppa1_all.deb
new file mode 100755
index 0000000..75f41c1
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx_1.0~beta+git20210222-1~ppa1_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/xfce4-dockbarx-plugin_0.6+git20210221-1~ppa2~20.10_arm64.deb b/external/cache/debs/extra/bullseye-desktop/xfce4-dockbarx-plugin_0.6+git20210221-1~ppa2~20.10_arm64.deb
new file mode 100755
index 0000000..78e2249
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/xfce4-dockbarx-plugin_0.6+git20210221-1~ppa2~20.10_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/xfce4-zorinmenulite-plugin_1.1.2_arm64.deb b/external/cache/debs/extra/bullseye-desktop/xfce4-zorinmenulite-plugin_1.1.2_arm64.deb
new file mode 100755
index 0000000..3eb9582
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/xfce4-zorinmenulite-plugin_1.1.2_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-utils/hostapd_2.9-102~orangepi2.1.8+1_arm64.deb b/external/cache/debs/extra/bullseye-utils/hostapd_2.9-102~orangepi2.1.8+1_arm64.deb
new file mode 100644
index 0000000..10394f9
Binary files /dev/null and b/external/cache/debs/extra/bullseye-utils/hostapd_2.9-102~orangepi2.1.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-utils/htop_3.1.0-0~armbian20.08.2+1_arm64.deb b/external/cache/debs/extra/bullseye-utils/htop_3.1.0-0~armbian20.08.2+1_arm64.deb
new file mode 100644
index 0000000..94f0d4f
Binary files /dev/null and b/external/cache/debs/extra/bullseye-utils/htop_3.1.0-0~armbian20.08.2+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb b/external/cache/debs/extra/bullseye-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb
new file mode 100644
index 0000000..78186af
Binary files /dev/null and b/external/cache/debs/extra/bullseye-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..98e76b3
Binary files /dev/null and b/external/cache/debs/extra/buster-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..b78f0b2
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..c887b29
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..1c92f7b
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..94c693b
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..c996ecd
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..11ea2a7
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..5345065
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..ed9e573
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..813c3c1
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..388932a
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..09fe136
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..8e1821a
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libump-dev_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libump-dev_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..cbe8a2b
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libump-dev_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libump_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libump_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..cbe1db4
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libump_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..2f8d6d7
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..637a6ed
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..ddf1bc1
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..887f3bd
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..e22c28a
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..6a30235
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..42fbae9
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..293a1ec
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..663ee6d
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..377b8cb
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..138b442
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/jammy-desktop/null.txt b/external/cache/debs/extra/jammy-desktop/null.txt
new file mode 100644
index 0000000..e69de29
diff --git a/external/cache/debs/extra/jammy-utils/hostapd_2.10-6~armbian22.02.3+1_arm64.deb b/external/cache/debs/extra/jammy-utils/hostapd_2.10-6~armbian22.02.3+1_arm64.deb
new file mode 100644
index 0000000..004c6a0
Binary files /dev/null and b/external/cache/debs/extra/jammy-utils/hostapd_2.10-6~armbian22.02.3+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..d3f0467
Binary files /dev/null and b/external/cache/debs/extra/stretch-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..ea387b8
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..fce073a
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..19b4547
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..eab57cc
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..c88912c
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..3331e9a
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/dri2-utils_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/dri2-utils_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..1aca914
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/dri2-utils_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..fbeb178
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..f84c990
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..b995891
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..0921e28
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libdri2-1_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libdri2-1_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..ca0c9f8
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libdri2-1_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libdri2-dev_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libdri2-dev_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..b9f16d5
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libdri2-dev_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libglshim_0.9.2~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libglshim_0.9.2~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..1a67632
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libglshim_0.9.2~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libmali-sunxi-dev_1.0-1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-dev_1.0-1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..2eab8ab
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-dev_1.0-1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libmali-sunxi-r3p0_1.0-1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-r3p0_1.0-1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..56dab32
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-r3p0_1.0-1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libump-dev_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libump-dev_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..2ebb772
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libump-dev_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libump_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libump_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..05ad60b
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libump_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libvdpau-dev_1.1.1-10~armbian5.73+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libvdpau-dev_1.1.1-10~armbian5.73+1_armhf.deb
new file mode 100755
index 0000000..32e0fcc
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libvdpau-dev_1.1.1-10~armbian5.73+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libvdpau-sunxi1_0.5.1~armbian5.73+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libvdpau-sunxi1_0.5.1~armbian5.73+1_armhf.deb
new file mode 100755
index 0000000..4ee681f
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libvdpau-sunxi1_0.5.1~armbian5.73+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..5dd1f2a
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..b9e08bf
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..4fd80de
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..864f5f6
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..3dad38b
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..4ed0f67
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..745cfe0
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..5860aaf
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..5c45b3a
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/h618/linux-u-boot-current-orangepizero2w_1.0.0_arm64.deb b/external/cache/debs/h618/linux-u-boot-current-orangepizero2w_1.0.0_arm64.deb
new file mode 100644
index 0000000..084ba0e
Binary files /dev/null and b/external/cache/debs/h618/linux-u-boot-current-orangepizero2w_1.0.0_arm64.deb differ
diff --git a/external/cache/debs/h618/linux-u-boot-current-orangepizero3_1.0.2_arm64.deb b/external/cache/debs/h618/linux-u-boot-current-orangepizero3_1.0.2_arm64.deb
new file mode 100644
index 0000000..9bfd1e2
Binary files /dev/null and b/external/cache/debs/h618/linux-u-boot-current-orangepizero3_1.0.2_arm64.deb differ
diff --git a/external/cache/sources/bananapi-config/LICENSE b/external/cache/sources/bananapi-config/LICENSE
new file mode 100644
index 0000000..d7f1051
--- /dev/null
+++ b/external/cache/sources/bananapi-config/LICENSE
@@ -0,0 +1,339 @@
+GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ {description}
+ Copyright (C) {year} {fullname}
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ {signature of Ty Coon}, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/external/cache/sources/bananapi-config/debian-config b/external/cache/sources/bananapi-config/debian-config
new file mode 100644
index 0000000..a383a9d
--- /dev/null
+++ b/external/cache/sources/bananapi-config/debian-config
@@ -0,0 +1,177 @@
+#!/bin/bash
+#
+# Copyright (c) Authors: http://www.armbian.com/authors, info@armbian.com
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+
+
+#
+# check for root privileges
+#
+if [[ $EUID != 0 ]]; then
+ echo "This tool requires root privileges. Try again with \"sudo \" please ..." >&2
+ sleep 2
+ exit 1
+fi
+
+
+
+
+#
+# check for internet connection to install dependencies
+#
+wget -q --spider www.baidu.com
+if [[ $? -ne 0 ]]; then
+ read -n 1 -s -p "Warning: Configuration cannot work properly without a working internet connection. \
+ Press CTRL C to stop or any key to ignore and continue."
+fi
+
+
+
+
+#
+# load functions, local first
+#
+if [[ -f ${BASH_SOURCE}-jobs ]]; then source ${BASH_SOURCE}-jobs;
+ elif [[ -f /usr/lib/bananapi-config/jobs.sh ]]; then source /usr/lib/bananapi-config/jobs.sh;
+ else exit 1;
+fi
+
+if [[ -f ${BASH_SOURCE}-submenu ]]; then source ${BASH_SOURCE}-submenu;
+ elif [[ -f /usr/lib/bananapi-config/submenu.sh ]]; then source /usr/lib/bananapi-config/submenu.sh;
+ else exit 1;
+fi
+
+if [[ -f ${BASH_SOURCE}-functions ]]; then source ${BASH_SOURCE}-functions;
+ elif [[ -f /usr/lib/bananapi-config/functions.sh ]]; then source /usr/lib/bananapi-config/functions.sh;
+ else exit 1;
+fi
+
+if [[ -f ${BASH_SOURCE}-functions-network ]]; then source ${BASH_SOURCE}-functions-network;
+ elif [[ -f /usr/lib/bananapi-config/functions-network.sh ]]; then source /usr/lib/bananapi-config/functions-network.sh;
+ else exit 1;
+fi
+
+
+# Script parameters handling
+while [[ $1 == *=* ]]; do
+ parameter=${1%%=*}
+ value=${1##*=}
+ shift
+ echo "Command line: setting $parameter to ${value:-(empty)}"
+ eval "$parameter=\"$value\""
+ scripted=true
+done
+
+# Display help
+if [[ $1 == "--help" ]]; then
+ echo "Banana Pi config options:"
+ echo ""
+ echo "Examples:"
+ echo ""
+ echo "Install headers: ${BASH_SOURCE[0]} main=Sytem selection=Headers"
+ echo "Update, upgrade and reboot: ${BASH_SOURCE[0]} main=System selection=Firmware"
+ echo "Switch to nightly builds: ${BASH_SOURCE[0]} main=System selection=Nightly"
+ echo "Switch to stable builds: ${BASH_SOURCE[0]} main=System selection=Stable"
+ echo "Install default desktop: ${BASH_SOURCE[0]} main=System selection=Default"
+ echo "Change to ZSH: ${BASH_SOURCE[0]} main=System selection=ZSH"
+ echo "Change to BASH: ${BASH_SOURCE[0]} main=System selection=BASH"
+ echo "Change to stable repository [branch=dev]: ${BASH_SOURCE[0]} main=System selection=Stable"
+ echo "Change to nightly repository [branch=dev]: ${BASH_SOURCE[0]} main=System selection=Nightly"
+ echo "Install headers: ${BASH_SOURCE[0]} main=Software selection=Headers_install"
+ echo "Remove headers: ${BASH_SOURCE[0]} main=Software selection=Headers_remove"
+ echo "Install kernel source: ${BASH_SOURCE[0]} main=Software selection=Source_install"
+ echo "Remove kernel source: ${BASH_SOURCE[0]} main=Software selection=Source_remove"
+ echo "Install Avahi mDNS/DNS-SD daemon: ${BASH_SOURCE[0]} main=Software selection=Avahi"
+ exit
+fi
+
+# collect info
+main "$@"
+
+#
+# Main menu
+#
+while true
+do
+ LIST=()
+
+ LIST+=( "System" "System and security settings" )
+ LIST+=( "Network" "Wired, wireless, Bluetooth, access point" )
+ LIST+=( "Personal" "Timezone, language, hostname" )
+ LIST+=( "Software" "System and 3rd party software install" )
+ LIST+=( "Help" "Documentation, support, sources" )
+
+ # count number of menu items to adjust window size
+ LISTLENGTH="$((11+${#LIST[@]}/2))"
+ BOXLENGTH=${#LIST[@]}
+ MENUTITLE="Configure \Z1$DISTRO $DISTROID\Z0"
+
+ # read cpu speed
+ POLICY="policy0"
+ [[ $(grep -c '^processor' /proc/cpuinfo) -gt 4 ]] && POLICY="policy4"
+ [[ ! -d /sys/devices/system/cpu/cpufreq/policy4 ]] && POLICY="policy0"
+ num=$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_min_freq 2> /dev/null)
+ if [[ -f /etc/default/cpufrequtils && ! -z "${num##*[!0-9]*}" ]]; then
+ LISTLENGTH=$((LISTLENGTH + 2))
+ MIN_CPU=$(($(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_min_freq) / 1000))
+ MAX_CPU=$(($(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_max_freq) / 1000))
+ GOVERNOR_CPU=$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_governor)
+ FREQENCIES="\nSoC runs between \Z1${MIN_CPU}\Z0 and \Z1${MAX_CPU} MHz\Z0 using \Z1${GOVERNOR_CPU}\Z0 governor.\n"
+ fi
+
+ [[ -n "${BOARD_NAME/ /}" ]] && MENUTITLE=$MENUTITLE" based \Z1BananaPi\Z0 for the \Z1${BOARD_NAME}\Z0 "
+
+ # main dialog routine
+ DIALOG_CANCEL=1
+ DIALOG_ESC=255
+ TITLELENGTH=${#MENUTITLE}
+
+ [[ "$TITLELENGTH" -lt 60 ]] && TITLELENGTH="60"
+
+if [[ -z $main ]]; then
+ exec 3>&1
+ main=$(dialog --colors --backtitle "$BACKTITLE" --title " bananapi-config " --clear \
+ --cancel-label "Exit" --menu "\n$MENUTITLE \n$FREQENCIES\nSupport: \Z1https://banana-pi.org\Z0\n " \
+ $LISTLENGTH ${TITLELENGTH} $BOXLENGTH "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+
+ [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && exit
+
+ dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox \
+ "\nLoading ${main,,} submodule ... " 5 $((26+${#main}))
+fi
+ case $main in
+
+ "System" )
+ submenu_settings
+ ;;
+
+ "Network" )
+ submenu_networking
+ ;;
+
+ "Personal" )
+ submenu_personal
+ ;;
+
+ "Software" )
+ submenu_software
+ ;;
+
+ "Help" )
+ unset main
+ t="This tool provides a straightforward way of configuring."
+ t=$t"\n \nAlthough it can be run at any time, some of the"
+ t=$t" options may have difficulties if you alter system settings manually.\n"
+ t=$t"\n\Z1Documentation:\Z0 https://banana-pi.org"
+ t=$t"\n\n\Z1Support:\Z0 https://banana-pi.org\n"
+ t=$t"\n\Z1Sources:\Z0 http://10.10.10.106:10000/Qubot"
+ show_box "Info" "$t" "18"
+ ;;
+ esac
+done
diff --git a/external/cache/sources/bananapi-config/debian-config-functions b/external/cache/sources/bananapi-config/debian-config-functions
new file mode 100644
index 0000000..df625bb
--- /dev/null
+++ b/external/cache/sources/bananapi-config/debian-config-functions
@@ -0,0 +1,823 @@
+#!/bin/bash
+#
+# Copyright (c) Authors: http://www.armbian.com/authors, info@armbian.com
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+# Functions:
+# main
+# check_desktop
+# exceptions
+# check_if_installed
+# is_package_manager_running
+# display_qr_code
+# beta_disclaimer
+# show_box
+# description
+# generic_select
+# reload_bsp
+# other_kernel_version
+# aval_dtbs
+# get_a20modes
+# get_h3modes
+# add_choose_user
+# google_token_allusers
+# configure_desktop
+
+
+#
+# gather info about the board and start with loading menu
+#
+function main(){
+
+ DIALOG_CANCEL=1
+ DIALOG_ESC=255
+
+ # we have our own lsb_release which does not use Python. Others shell install it here
+ if [[ ! -f /usr/bin/lsb_release ]]; then
+ if is_package_manager_running; then
+ sleep 3
+ fi
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt -y -qq --allow-downgrades --no-install-recommends install lsb-release
+ fi
+
+ [[ -f /etc/bananapi-release ]] && source /etc/bananapi-release && BANANAPI="Banana Pi $VERSION $IMAGE_TYPE";
+ DISTRO=$(lsb_release -is)
+ DISTROID=$(lsb_release -sc)
+ KERNELID=$(uname -r)
+ [[ -z "${BANANAPI// }" ]] && BANANAPI="$DISTRO $DISTROID"
+ DEFAULT_ADAPTER=$(ip -4 route ls | grep default | tail -1 | grep -Po '(?<=dev )(\S+)')
+ LOCALIPADD=$(ip -4 addr show dev $DEFAULT_ADAPTER | awk '/inet/ {print $2}' | cut -d'/' -f1)
+ BACKTITLE="Configuration utility, $BANANAPI"
+ [[ -n "$LOCALIPADD" ]] && BACKTITLE=$BACKTITLE", "$LOCALIPADD
+ TITLE="$BOARD_NAME "
+ [[ -z "${DEFAULT_ADAPTER// }" ]] && DEFAULT_ADAPTER="lo"
+ OVERLAYDIR="/boot/dtb/overlay";
+ [[ "$LINUXFAMILY" == "sunxi64" ]] && OVERLAYDIR="/boot/dtb/allwinner/overlay";
+ [[ "$LINUXFAMILY" == "meson64" ]] && OVERLAYDIR="/boot/dtb/amlogic/overlay";
+ [[ "$LINUXFAMILY" == "rockchip64" ]] && OVERLAYDIR="/boot/dtb/rockchip/overlay";
+ [[ "$LINUXFAMILY" == "rockchip-rk3588" ]] && OVERLAYDIR="/boot/dtb/rockchip/overlay";
+ [[ "$LINUXFAMILY" == "sun50iw9" && "$BRANCH" == "current" ]] && OVERLAYDIR="/boot/dtb/sunxi/overlay";
+ [[ "$LINUXFAMILY" == "sun50iw9" && "$BRANCH" == "next" ]] && OVERLAYDIR="/boot/dtb/allwinner/overlay";
+ [[ "$LINUXFAMILY" == "rockchip-rk356x" ]] && OVERLAYDIR="/boot/dtb/rockchip/overlay";
+ # detect desktop
+ check_desktop
+ dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nLoading Orange Pi configuration utility ... " 5 45
+ sleep 1
+
+}
+
+
+
+
+#
+# compare two strings in dot separated version format
+#
+vercomp () {
+
+ if [[ $1 == $2 ]]
+ then
+ return 0
+ fi
+ local IFS=.
+ local i ver1=($1) ver2=($2)
+ # fill empty fields in ver1 with zeros
+ for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
+ do
+ ver1[i]=0
+ done
+ for ((i=0; i<${#ver1[@]}; i++))
+ do
+ if [[ -z ${ver2[i]} ]]
+ then
+ # fill empty fields in ver2 with zeros
+ ver2[i]=0
+ fi
+ if ((10#${ver1[i]} > 10#${ver2[i]}))
+ then
+ return 1
+ fi
+ if ((10#${ver1[i]} < 10#${ver2[i]}))
+ then
+ return 2
+ fi
+ done
+ return 0
+
+}
+
+
+
+
+#
+# test compare two strings $1="3.4.12" $2="5.4.2" $3="<" returns 0 if relation is correct
+#
+testvercomp () {
+
+ vercomp $1 $2
+ case $? in
+ 0) op='=';;
+ 1) op='>';;
+ 2) op='<';;
+ esac
+ if [[ $op != $3 ]]
+ then
+ return 1
+ else
+ return 0
+ fi
+
+}
+
+
+
+
+#
+# read desktop parameters
+#
+function check_desktop()
+{
+
+ DISPLAY_MANAGER=""; DESKTOP_INSTALLED=""
+ check_if_installed nodm && DESKTOP_INSTALLED="nodm";
+ check_if_installed lightdm && DESKTOP_INSTALLED="lightdm";
+ check_if_installed gdm && DESKTOP_INSTALLED="gdm";
+ [[ -n $(service lightdm status 2> /dev/null | grep -w active) ]] && DISPLAY_MANAGER="lightdm"
+ [[ -n $(service nodm status 2> /dev/null | grep -w active) ]] && DISPLAY_MANAGER="nodm"
+ [[ -n $(service gdm status 2> /dev/null | grep -w active) ]] && DISPLAY_MANAGER="gdm"
+
+}
+
+
+
+
+#
+# naming exceptions for packages
+#
+function exceptions ()
+{
+
+ TARGET_FAMILY=$LINUXFAMILY
+ UBOOT_BRANCH=$TARGET_BRANCH # uboot naming is different
+
+ if [[ $TARGET_BRANCH == "default" ]]; then TARGET_BRANCH=""; else TARGET_BRANCH="-"$TARGET_BRANCH; fi
+ # pine64
+ if [[ $TARGET_FAMILY == pine64 ]]; then
+ TARGET_FAMILY="sunxi64"
+ fi
+ # allwinner legacy kernels
+ if [[ $TARGET_FAMILY == sun*i ]]; then
+ TARGET_FAMILY="sunxi"
+ if [[ $UBOOT_BRANCH == "default" ]]; then
+ TARGET_FAMILY=$(cat /proc/cpuinfo | grep "Hardware" | sed 's/^.*Allwinner //' | awk '{print $1;}')
+ fi
+ fi
+
+}
+
+
+
+
+#
+# check dpkg status of $1 -- currently only 'not installed at all' case caught
+#
+check_if_installed (){
+
+ local DPKG_Status="$(dpkg -s "$1" 2>/dev/null | awk -F": " '/^Status/ {print $2}')"
+ if [[ "X${DPKG_Status}" = "X" || "${DPKG_Status}" = *deinstall* ]]; then
+ return 1
+ else
+ return 0
+ fi
+
+}
+
+
+
+
+#
+# check if package manager is doing something
+#
+function is_package_manager_running() {
+
+ if ps -C apt-get,apt,dpkg >/dev/null ; then
+ [[ -z $scripted ]] && dialog --colors --title " \Z1Error\Z0 " --backtitle "$BACKTITLE" --no-collapse --msgbox \
+ "\n\Z0Package manager is running in the background. \n\nCan't install dependencies. Try again later." 9 53
+ return 0
+ else
+ return 1
+ fi
+
+}
+
+
+
+
+#
+# wget with dialog progress bar $1=URL $2=parameters
+#
+function fancy_wget()
+{
+
+ LANG=C wget $2 --progress=bar:force:noscroll $1 2>&1 | stdbuf -i0 -o0 -e0 tr '>' '\n' | \
+ stdbuf -i0 -o0 -e0 sed -rn 's/^.*\<([0-9]+)%\[.*$/\1/p' | dialog --backtitle "$BACKTITLE" --title " Downloading " \
+ --gauge "Please wait" 7 70 0
+
+}
+
+
+
+
+#
+# display qr code for authentication method
+#
+function display_qr_code()
+{
+
+ clear
+ SECRET=$(head -1 /root/.google_authenticator)
+ qrencode -m 2 -d 9 -8 -t ANSI256 "otpauth://totp/test?secret=$SECRET"
+ echo -e "\nHow to setup your one type password generator?\n"
+ echo -e "\nInstall a one-time password authenticator on your mobile device (e.g. FreeOTP) from the Android \
+market or F-Droid. \n\nIn the application menu, click the corresponding button to create a new account and either \
+scan the QR code or enter the secret key manually:\\n\n$SECRET \n\nYou should now see a new passcode token being \
+generated every 60 seconds on your phone.\n" | fold -sw 60
+ read -n 1 -s -r -p "Press any key to continue"
+
+}
+
+
+
+
+#
+# show disclaimer
+#
+function beta_disclaimer ()
+{
+
+ exec 3>&1
+ ACKNOWLEDGEMENT=$(dialog --colors --nocancel --backtitle "$BACKTITLE" --no-collapse --title " Warning " \
+ --clear \--radiolist "\n$1\n \n" 0 56 5 "Yes, I understand" "" off 2>&1 1>&3)
+ exec 3>&-
+
+}
+
+
+
+
+#
+# show box
+#
+function show_box ()
+{
+
+ dialog --colors --backtitle "$BACKTITLE" --no-collapse --title " $1 " --clear --msgbox "\n$2\n \n" $3 56
+
+}
+
+
+
+
+#
+# show description for MOTD files
+#
+function description
+{
+ case $1 in
+ *header*)
+ echo "Big board logo and kernel info"
+ ;;
+ *sysinfo*)
+ echo "Sysinfo - load, ip, memory, uptime, ..."
+ ;;
+ *tips*)
+ echo "Shows tip of the day"
+ ;;
+ *updates*)
+ echo "Display number of available updates"
+ ;;
+ *bananapi-config*)
+ echo "Show command for system configuration"
+ ;;
+ *autoreboot-warn*)
+ echo "Show warning when reboot is needed"
+ ;;
+ *uk.armbian.com*)
+ echo "United Kingdom"
+ ;;
+ *mirrors.tuna.tsinghua.edu.cn/armbian/*)
+ echo "China"
+ ;;
+ *mirrors.netix.net/armbian/apt/*)
+ echo "Bulgarija"
+ ;;
+ *mirrors.dotsrc.org/armbian-apt/*)
+ echo "Denmark"
+ ;;
+ *.armbian.com*)
+ echo "Estonia"
+ ;;
+ *)
+ echo ""
+ ;;
+ esac
+}
+
+
+#
+# Generic select box
+#
+function generic_select()
+{
+ IFS=$' '
+ PARAMETER=($1)
+ local LIST=()
+ for i in "${PARAMETER[@]}"
+ do
+ if [[ -n $3 ]]; then
+ [[ ${i[0]} -ge $3 ]] && \
+ LIST+=( "${i[0]//[[:blank:]]/}" "" )
+ else
+ LIST+=( "${i[0]//[[:blank:]]/}" "" )
+ fi
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ if [ "$LIST_LENGTH" -eq 1 ]; then
+ PARAMETER=${PARAMETER[0]}
+ else
+ exec 3>&1
+ PARAMETER=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \
+ --title "$2" --clear --menu "" $((6+${LIST_LENGTH})) 0 $((1+${LIST_LENGTH})) "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+}
+
+
+
+
+#
+# reload kernel, bsp and bananapi-config
+#
+function reload_bsp(){
+
+ # switch to defined branch
+ [[ -n "$1" ]] && BRANCH=$1
+
+ # deal with exceptions
+ if [[ $BRANCH == current || $BRANCH == dev ]]; then
+ [[ ${LINUXFAMILY} == rk3399 ]] && LINUXFAMILY=rockchip64
+ fi
+
+ clear
+ debconf-apt-progress -- apt-get update
+
+ # must exits
+ PACKAGE_INSTALL="linux-image-${BRANCH}-${LINUXFAMILY} linux-dtb-${BRANCH}-${LINUXFAMILY}"
+ PACKAGE_PURGE="linux-image* linux-dtb*"
+
+ # create install and remove logic
+ command=$(LC_ALL=C apt-get --download-only --simulate --allow-downgrades -y --no-install-recommends install linux-${DISTROID}-root-${BRANCH}-${BOARD} 2>/dev/null)
+ if [[ $? -eq 0 && -z $(echo $command | grep "not possible") ]]; then
+ PACKAGE_INSTALL+=" linux-${DISTROID}-root-${BRANCH}-${BOARD}"
+ PACKAGE_PURGE+=" linux-${DISTROID}-root*"
+ fi
+
+ command=$(LC_ALL=C apt-get --download-only --simulate --reinstall --allow-downgrades -y --no-install-recommends install linux-u-boot-${BOARD}-${BRANCH} 2>/dev/null)
+ if [[ $? -eq 0 && -z $(echo $command | grep "not possible") ]]; then
+ PACKAGE_INSTALL+=" linux-u-boot-${BOARD}-${BRANCH}"
+ PACKAGE_PURGE+=" linux-u-boot-${BOARD}-*"
+ fi
+
+ if check_if_installed bananapi-${DISTROID}-desktop ; then
+ PACKAGE_INSTALL+=" bananapi-${DISTROID}-desktop"
+ PACKAGE_PURGE+=" bananapi-${DISTROID}-desktop*"
+ fi
+
+ if check_if_installed linux-headers-${BRANCH}-${FAMILY} ; then
+ PACKAGE_INSTALL+=" linux-headers-${BRANCH}-${FAMILY}"
+ PACKAGE_PURGE+=" linux-headers*"
+ fi
+
+ debconf-apt-progress -- apt-get -o Dpkg::Options::="--force-confold" --force-yes --download-only --allow-downgrades -y --no-install-recommends install $PACKAGE_INSTALL
+ # if download is ok, remove old packages
+ if [[ $? = 0 ]]; then
+
+ debconf-apt-progress -- apt-get -y -qq purge $PACKAGE_PURGE
+ find "/boot/" -name "System.map*" -type f -delete
+ find "/boot/" -name "config*" -type f -delete
+ find "/boot/" -name "vmlinuz*" -type f -delete
+ find "/boot/" -name "*nitrd*" -type f -delete
+ find "/boot/" -name "*Image" -type l -delete
+
+ # install packages
+ echo $PACKAGE_INSTALL >> /var/log/upgrade.log
+ debconf-apt-progress -- apt-get -y -qq --allow-downgrades --no-install-recommends --reinstall \
+ -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install $PACKAGE_INSTALL
+
+ if [[ $? -eq 1 ]]; then
+ echo "Something went wrong ... check logs."; exit;
+ else
+ apt clean
+ fi
+
+ fi
+
+}
+
+
+
+
+function other_kernel_version ()
+{
+
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+ local HIDDEN='hidden'
+
+ # get current kernel information
+ CURRENT_VERSION_TEMP=$(dpkg -l | grep '^ii' | grep linux-image)
+ CURRENT_VERSION=$(echo $CURRENT_VERSION_TEMP | awk '{print $2}')"="$(echo $CURRENT_VERSION_TEMP | awk '{print $3}')
+
+ # Merge families and handle exceptions
+ [[ ${LINUXFAMILY} == sun*i ]] && LINUXFAMILY=sunxi
+ [[ ${LINUXFAMILY} == pine64 ]] && LINUXFAMILY=sunxi64
+ [[ ${LINUXFAMILY} == sun*iw* ]] && LINUXFAMILY=sunxi64
+ [[ ${LINUXFAMILY} == cubox || ${LINUXFAMILY} == udoo ]] && LINUXFAMILY=imx6
+ [[ ${BOARD} == odroidc2 || ${BOARD} == kvim1 || ${BOARD} == lafrite || ${BOARD} == lepotato || ${BOARD} == nanopik2-s905 ]] && HIDDEN="legacy"
+ [[ ${LINUXFAMILY} == odroidn2 ]] && LINUXFAMILY=meson64
+
+ # check what is available from the repository
+ debconf-apt-progress -- apt-get update
+ LIST=($(apt-cache show linux-image*${LINUXFAMILY} | grep -E "Package:|Version:|version:" \
+ | grep -v "Config-Version" | sed -n -e 's/^.*: //p' | sed 's/\.$//g'))
+ new_list=()
+
+ # create a human readable menu
+ for ((n=0;n<$((${#LIST[@]}));n++));
+ do
+ m=$(( $n + 1 ))
+ prvi=$((3*$m - 3))
+ drugi=$((3*$m - 2))
+ tretji=$((3*$m - 1))
+ [[ -z ${LIST[$prvi]} ]] && break
+ if [[ $CURRENT_VERSION != "${LIST[$prvi]}=${LIST[$drugi]}" && ${LIST[$prvi]} != *${HIDDEN}* ]]; then
+ new_list+=( "${LIST[$prvi]}=${LIST[$drugi]}" )
+ new_list+=( ${LIST[$tretji]} )
+ fi
+ local tmp="${LIST[$prvi]}=${LIST[$drugi]}${LIST[$tretji]}"
+ [[ ${#tmp} -gt $chrlen ]] && local chrlen=${#tmp}
+ done
+
+ # copy back to main array
+ LIST=("${new_list[@]}")
+ LIST_LENGTH=$((${#LIST[@]}/2));
+
+ if [ "$LIST_LENGTH" -eq 0 ]; then
+ dialog --backtitle "$BACKTITLE" --title " Warning " --msgbox "\nNo other kernels available!" 7 32
+ else
+ beta_disclaimer "Switching between kernels might change functionality of your board or it might fail to boot. \
+ \n\n\Z1In case of troubles expect no help!\Z0"
+ if [[ -n $ACKNOWLEDGEMENT ]]; then
+ exec 3>&1
+ TARGET_VERSION=$(dialog --ok-label "Reboot" --cancel-label "Cancel" --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select kernel and reboot" --clear --menu "" $((6+${LIST_LENGTH})) $((7+${chrlen})) 25 "${LIST[@]}" 2>&1 1>&3)
+ exitstatus=$?;
+ exec 3>&-
+ if [[ $exitstatus = 0 ]]; then
+ IFS=" "
+
+ # determine upgrade packages
+ UPGRADE_ROOT="default"
+ UPGRADE_UBOOT=""
+ [[ $TARGET_VERSION == *legacy* ]] && UPGRADE_ROOT="-legacy" && UPGRADE_UBOOT="legacy"
+ [[ $TARGET_VERSION == *next* ]] && UPGRADE_ROOT="-next" && UPGRADE_UBOOT="next"
+ [[ $TARGET_VERSION == *current* ]] && UPGRADE_ROOT="-current" && UPGRADE_UBOOT="current"
+ [[ $TARGET_VERSION == *dev* ]] && UPGRADE_ROOT="-dev" && UPGRADE_UBOOT="dev"
+
+ # install packages
+ PACKAGE_LIST="$TARGET_VERSION"
+ TARGET_VERSION_DTB=${TARGET_VERSION/image/dtb}
+ TARGET_VERSION_PRE=$(echo $TARGET_VERSION_DTB | cut -f1 -d"=")
+ TARGET_VERSION_SUB=$(echo $TARGET_VERSION_DTB | cut -f2 -d"=")
+ [[ -n $(apt-cache madison "$TARGET_VERSION_PRE" | grep $TARGET_VERSION_SUB ) ]] && \
+ # installs u-boot only if exits
+ apt-cache show linux-u-boot-${BOARD}-${UPGRADE_UBOOT} 2> /dev/null
+ [[ $? -eq 0 ]] && PACKAGE_LIST=$PACKAGE_LIST" linux-u-boot-${BOARD}-${UPGRADE_UBOOT}"
+
+ PACKAGE_LIST=$PACKAGE_LIST" $TARGET_VERSION_DTB"
+ echo $PACKAGE_LIST > /tmp/switch_kernel.log 2>&1
+ debconf-apt-progress -- apt -o Dpkg::Options::="--force-confold" --force-yes --download-only --allow-downgrades -y --no-install-recommends install $PACKAGE_LIST
+
+ if [[ $? = 0 ]]; then
+ dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nRemoving current kernel ..." 5 36
+
+ # remove old kernel
+ debconf-apt-progress -- apt -y -qq purge linux-u-boot* linux-image* linux-dtb* linux-headers* linux-${DISTROID}-root*
+
+ # cleanup
+ find "/boot/" -name "System.map*" -type f -delete; find "/boot/" -name "config*" -type f -delete
+ find "/boot/" -name "vmlinuz*" -type f -delete; find "/boot/" -name "*nitrd*" -type f -delete
+ apt clean
+ # BSP must be installed separate otherwise it won't work
+ debconf-apt-progress -- apt -o Dpkg::Options::="--force-confold" --force-yes -y -qq --allow-downgrades --no-install-recommends install linux-${DISTROID}-root${UPGRADE_ROOT}-${BOARD}
+ debconf-apt-progress -- apt -o Dpkg::Options::="--force-confold" --force-yes -y -qq --allow-downgrades --no-install-recommends install $PACKAGE_LIST
+ if [[ $? = 0 ]]; then
+ # update boot loader
+ [[ -f /usr/lib/u-boot/platform_install.sh ]] && source /usr/lib/u-boot/platform_install.sh
+ #recognize_root
+ root_uuid=$(sed -e 's/^.*root=//' -e 's/ .*$//' < /proc/cmdline)
+ root_partition=$(blkid | tr -d '":' | grep "${root_uuid}" | awk '{print $1}')
+ root_partition_device="${root_partition::-2}"
+ write_uboot_platform "$DIR" "${root_partition_device}"
+ reboot
+ fi
+ else
+ dialog --backtitle "$BACKTITLE" --title "Warning" --msgbox \
+ "\nTest install failed. Can't change firmware \n\nCheck /tmp/switch_kernel.log" 9 48
+ fi
+ fi
+ fi
+ fi
+}
+
+
+
+
+#
+# check if board has alternative kernels
+#
+function aval_dtbs ()
+{
+
+ if [[ $LINUXFAMILY == cubox ]]; then
+ local width=80
+ LIST=("imx6dl-hummingboard.dtb" "HB Solo/DualLite" "imx6dl-hummingboard-emmc-som-v15.dtb" "HB Solo/DualLite v1.5 with eMMC" "imx6dl-hummingboard-som-v15.dtb" "HB Solo/DualLite v1.5" \
+ "imx6dl-hummingboard2.dtb" "HB2 Solo/DualLite" "imx6dl-hummingboard2-emmc-som-v15.dtb" "HB2 Solo/DualLite v1.5 with eMMC" "imx6dl-hummingboard2-som-v15.dtb" "HB2 Solo/DualLite v1.5" \
+ "imx6q-hummingboard.dtb" "HB Dual/Quad" "imx6q-hummingboard-emmc-som-v15.dtb" "HB Dual/Quad v1.5 with eMMC" "imx6q-hummingboard-som-v15.dtb" "HB Dual/Quad v1.5" \
+ "imx6q-hummingboard2.dtb" "HB2 Dual/Quad" "imx6q-hummingboard2-emmc-som-v15.dtb" "HB2 Dual/Quad v1.5 with eMMC" "imx6q-hummingboard2-som-v15.dtb" "HB2 Dual/Quad v1.5" \
+ "imx6dl-cubox-i.dtb" "Cubox-i Solo/DualLite" "imx6dl-cubox-i-emmc-som-v15.dtb" "Cubox-i Solo/DualLite v1.5 with eMMC" "imx6dl-cubox-i-som-v15.dtb" "Cubox-i Solo/DualLite v1.5" \
+ "imx6q-cubox-i.dtb" "Cubox-i Dual/Quad" "imx6q-cubox-i-emmc-som-v15.dtb" "Cubox-i Dual/Quad v1.5 with eMMC" "imx6q-cubox-i-som-v15.dtb" "Cubox-i Dual/Quad v1.5")
+ else
+ local width=52
+ LIST=("xu4" "Odroid XU4" "xu3" "Odroid XU3" "xu3l" "Odroid XU3 Lite" "hc1" "Odroid HC1/HC2")
+ fi
+
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ if [ "$LIST_LENGTH" -eq 1 ]; then
+ TARGET_BOARD=${AVAL_KERNEL[0]}
+ else
+ exec 3>&1
+ TARGET_BOARD=$(dialog --cancel-label "Cancel" --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select optimised board configuration" --clear --menu \
+ "" $((6+${LIST_LENGTH})) ${width} 25 "${LIST[@]}" 2>&1 1>&3)
+ exitstatus=$?;
+ exec 3>&-
+ fi
+
+}
+
+
+
+
+#
+# select video modes for a10 and a20
+#
+function get_a20modes ()
+{
+
+ IFS=$'\r'
+ GLOBIGNORE='*'
+ SCREEN_RESOLUTION=("1920x1080p60" "1280x720p60" "1920x1080p50" "1280x1024p60" "1024x768p60" "800x600p60" "640x480p60" "1360x768p60" "1440x900p60" "1680x1050p60")
+ local LIST=()
+ for i in "${SCREEN_RESOLUTION[@]}"
+ do
+ LIST+=( "${i[0]//[[:blank:]]/}" "" )
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ #echo $LIST_LENGTH
+ #exit
+ if [ "$LIST_LENGTH" -eq 1 ]; then
+ SCREEN_RESOLUTION=${SCREEN_RESOLUTION[0]}
+ else
+ exec 3>&1
+ SCREEN_RESOLUTION=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select video mode" --clear --menu \
+ "" $((6+${LIST_LENGTH})) 25 $((1+${LIST_LENGTH})) "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+
+}
+
+
+
+
+#
+# select video modes for odroid c1/c2
+#
+function get_odroidmodes ()
+{
+
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+ SCREEN_RESOLUTION=($(cat /boot/boot.ini | grep -w "# setenv" | grep "hz" | cut -d'"' -f 2))
+ SCREEN_RESOLUTION=($(cat /boot/boot.ini | grep "Progressive" | grep -v "setenv" | cut -d'"' -f 2))
+ local LIST=()
+ for i in "${SCREEN_RESOLUTION[@]}"
+ do
+ LIST+=( "${i[0]//[[:blank:]]/}" "" )
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ #echo $LIST_LENGTH
+ #exit
+ if [ "$LIST_LENGTH" -eq 1 ]; then
+ SCREEN_RESOLUTION=${SCREEN_RESOLUTION[0]}
+ else
+ exec 3>&1
+ SCREEN_RESOLUTION=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select video mode" --clear --menu \
+ "" $((6+${LIST_LENGTH})) 25 $((1+${LIST_LENGTH})) "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+
+}
+
+
+
+
+#
+# select video modes for h3
+#
+function get_h3modes ()
+{
+
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+ SCREEN_RESOLUTION=($(h3disp -i clean))
+ local LIST=()
+ for i in "${SCREEN_RESOLUTION[@]}"
+ do
+ LIST+=( "${i[0]//[[:blank:]]/}" "" )
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ #echo $LIST_LENGTH
+ #exit
+ if [ "$LIST_LENGTH" -eq 1 ]; then
+ SCREEN_RESOLUTION=${SCREEN_RESOLUTION[0]}
+ else
+ exec 3>&1
+ SCREEN_RESOLUTION=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select video mode" --clear --menu \
+ "" $((6+${LIST_LENGTH})) 25 $((1+${LIST_LENGTH})) "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+
+}
+
+
+
+
+#
+# create or pick unprivileged user
+#
+function add_choose_user ()
+{
+
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+
+ local USERS=($(awk -F'[/:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' /etc/passwd))
+ local LIST=()
+ for i in "${USERS[@]}"
+ do
+ LIST+=( "${i[0]//[[:blank:]]/}" "" )
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+
+ if [ "$LIST_LENGTH" -eq 0 ]; then
+ dialog --backtitle "$BACKTITLE" --title " Notice " --msgbox \
+ "\nWe didn't find any unprivileged user with sudo rights which is required to run this service.\
+ \n\nPress enter to create one!" 10 48
+ read -t 0 temp
+ echo -e "\nPlease provide a username (eg. your forename) or leave blank for canceling user creation: \c"
+ read -e username
+ CHOSEN_USER="$(echo "$username" | tr '[:upper:]' '[:lower:]' | tr -d -c '[:alnum:]')"
+ [ -z "$CHOSEN_USER" ] && return
+ echo "Trying to add user $CHOSEN_USER"
+ adduser $CHOSEN_USER || return
+ elif [ "$LIST_LENGTH" -eq 1 ]; then
+ CHOSEN_USER=${USERS[0]}
+ else
+ exec 3>&1
+ CHOSEN_USER=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select unprivileged user" --clear --menu "" $((6+${LIST_LENGTH})) 40 15 "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+
+}
+
+
+
+
+#
+# Copy Google token to all local users.
+#
+function google_token_allusers ()
+{
+
+ if [[ -f /root/.google_authenticator ]]; then
+ local USERS=($(awk -F'[/:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' /etc/passwd))
+ for i in "${USERS[@]}"
+ do
+ USER=${i[0]//[[:blank:]]/}
+ if [[ -d /home/$USER ]]; then
+ cp /root/.google_authenticator /home/$USER/
+ chown ${USER}:${USER} /home/${USER}/.google_authenticator
+ fi
+ done
+ fi
+
+}
+
+
+
+
+#
+# configure bananapi desktop
+#
+function configure_desktop ()
+{
+
+ add_choose_user
+
+ if [ -n "$CHOSEN_USER" ]; then
+
+ # update packages
+ debconf-apt-progress -- apt-get update
+
+ # install new package if exists
+ unset PACKAGE_SUFIX
+ [[ -n $(apt-cache search --names-only "^bananapi-${DISTROID}-desktop-xfce$") ]] && PACKAGE_SUFIX="-xfce"
+
+ # remove desktop package to secure proper install
+ if check_if_installed bananapi-${DISTROID}-desktop ; then
+ debconf-apt-progress -- apt-get -y \
+ remove bananapi-${DISTROID}-desktop${PACKAGE_SUFIX} lightdm lightdm-gtk-greeter
+ fi
+
+ # install desktop package
+ debconf-apt-progress -- apt-get --reinstall -o Dpkg::Options::="--force-confdef" \
+ -o Dpkg::Options::="--force-confold" -y \
+ install $1 bananapi-${DISTROID}-desktop${PACKAGE_SUFIX} lightdm lightdm-gtk-greeter
+
+ # in case previous install was interrupted
+ [[ $? -eq 130 ]] && dpkg --configure -a
+
+ # clean apt cache
+ apt clean
+
+ # add user to groups
+ for additionalgroup in sudo netdev audio video dialout plugdev input bluetooth systemd-journal ssh; do
+ usermod -aG ${additionalgroup} ${CHOSEN_USER} 2>/dev/null
+ done
+
+ # Prevent loading paralel printer port drivers which we don't need here.
+ # suppress boot error if kernel modules are absent
+ if [[ -f /etc/modules-load.d/cups-filters.conf ]]; then
+ sed "s/^lp/#lp/" -i /etc/modules-load.d/cups-filters.conf
+ sed "s/^ppdev/#ppdev/" -i /etc/modules-load.d/cups-filters.conf
+ sed "s/^parport_pc/#parport_pc/" -i /etc/modules-load.d/cups-filters.conf
+ fi
+
+ # enable show windows content on stronger boards
+ cpu_cores=$(grep -c '^processor' /proc/cpuinfo | sed 's/^0$/1/')
+ if [[ ${cpu_cores} -gt 2 && -f /etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml ]]; then
+ sed -i 's//g' \
+ /etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml
+ fi
+
+ # fix for gksu in Xenial
+ touch /home/${CHOSEN_USER}/.Xauthority
+ cp -R /etc/skel/. /home/${CHOSEN_USER}
+
+ # set up profile sync daemon on desktop systems
+ which psd >/dev/null 2>&1
+ if [[ $? -eq 0 && -z $(grep overlay-helper /etc/sudoers) ]]; then
+ echo "${CHOSEN_USER} ALL=(ALL) NOPASSWD: /usr/bin/psd-overlay-helper" >> /etc/sudoers
+ touch /home/${CHOSEN_USER}/.activate_psd
+ fi
+
+ mkdir -p /etc/lightdm/lightdm.conf.d
+ echo "[Seat:*]" > /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ echo "autologin-user=$CHOSEN_USER" >> /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ echo "autologin-user-timeout=0" >> /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ echo "user-session=xfce" >> /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ ln -s /lib/systemd/system/lightdm.service /etc/systemd/system/display-manager.service >/dev/null 2>&1
+ # fix permissions
+ chown -R ${CHOSEN_USER}:${CHOSEN_USER} /home/${CHOSEN_USER}/.
+ service lightdm start >/dev/null 2>&1
+ fi
+
+}
diff --git a/external/cache/sources/bananapi-config/debian-config-functions-network b/external/cache/sources/bananapi-config/debian-config-functions-network
new file mode 100755
index 0000000..cc8a137
--- /dev/null
+++ b/external/cache/sources/bananapi-config/debian-config-functions-network
@@ -0,0 +1,741 @@
+#!/bin/bash
+#
+# Copyright (c) 2017 Igor Pecovnik, igor.pecovnik@gma**.com
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+# Functions:
+# initialize_lte
+# function lte
+# check_hostapd
+# check_advanced_modes
+# create_if_config
+# reload-nety
+# check_port
+# check_ht_capab
+# check_vht_capab
+# check_channels
+# netmask_to_cidr
+# nm_ip_editor
+# systemd_ip_editor
+# ip_editor
+# wlan_edit_basic
+# wlan_edit
+# wlan_exceptions
+# check_and_warn
+# get_wlan_interface
+# select_default_interface
+# connect_bt_interface
+
+
+
+#
+# 3G/4G general stuff
+#
+function initialize_lte ()
+{
+# This file defines udev rules for some 3G/UMTS/LTE modems. It
+# addresses the issue that the ttyUSB devices are numbered randomly, and
+# their numbering can vary between server reboots. These rules create
+# persistent symlinks which can be reliably used in WWAN interface
+# startup scripts.
+
+# These rules assume that there is only one WWAN modem in the system. In
+# order to address multiple WWAN cards, the rules need to be more
+# specific and associate with serial numbers of the modems.
+
+# Copyright (c) 2016 Stanislav Sinyagin .
+
+# This content is published under Creative Commons Attribution 4.0
+# International (CC BY 4.0) license.
+# Source repository: https://github.com/ssinyagin/wwan_udev_rules
+
+if ! check_if_installed ppp then; then
+ apt-get -y -qq install ppp >/dev/null 2>&1
+fi
+cat >/etc/udev/rules.d/99-wwan.rules <<'EOT'
+
+
+# Source repository: https://github.com/ssinyagin/wwan_udev_rules
+
+# Huawei ME909s-120 LTE modem
+SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="15c1", SYMLINK+="ttyWWAN%E{ID_USB_INTERFACE_NUM}"
+SUBSYSTEM=="net", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="15c1", NAME="lte0"
+
+# Huawei MU709s-2 UMTS modem
+SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1c25", SYMLINK+="ttyWWAN%E{ID_USB_INTERFACE_NUM}"
+SUBSYSTEM=="net", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1c25", NAME="umts0"
+
+# Qualcomm Gobi2000
+SUBSYSTEM=="tty", ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="251d", SYMLINK+="ttyWWAN%E{ID_USB_INTERFACE_NUM}"
+
+# Sierra Wireless MC8775
+SUBSYSTEM=="tty", ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1e1d", SYMLINK+="ttyWWAN%E{.ID_PORT}"
+
+# Novatel Wireless, Inc. Expedite E371
+SUBSYSTEM=="tty", ATTRS{idVendor}=="413c", ATTRS{idProduct}=="819b", SYMLINK+="ttyWWAN%E{ID_USB_INTERFACE_NUM}"
+
+# SIMCom SIM7100
+SUBSYSTEM=="tty", ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", SYMLINK+="ttyWWAN%E{ID_USB_INTERFACE_NUM}"
+SUBSYSTEM=="net", ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", NAME="lte0"
+EOT
+
+# reload udev rules
+udevadm control --reload-rules && udevadm trigger
+}
+
+
+
+
+#
+# 3G/4G init scripts add + remove
+#
+function lte ()
+{
+case $1 in
+ "12d1:15c1" )
+ # Huawei ME909s-120 LTE modem
+ LTE_MODEM_ID=$1
+ if [[ $2 == on && $(cat /sys/class/net/lte0/operstate) == "up" ]]; then
+ show_box "Warning" "Huawei ME909s-120 LTE modem is up and running" 7
+ elif [[ $2 == on ]]; then
+ show_box "Info" "Huawei ME909s-120 LTE modem will try to connect" 7
+cat >/etc/chatscripts/sunrise.HUAWEI <<'EOT'
+ABORT BUSY
+ABORT 'NO CARRIER'
+ABORT ERROR
+TIMEOUT 10
+'' ATZ
+OK 'AT+CFUN=1'
+OK 'AT+CMEE=1'
+OK 'AT\^NDISDUP=1,1,"internet"'
+OK
+EOT
+cat >/etc/chatscripts/gsm_off.HUAWEI <<'EOT'
+ABORT ERROR
+TIMEOUT 5
+'' AT+CFUN=0 OK
+EOT
+
+cat >/etc/network/interfaces.d/lte0 <<'EOT'
+allow-hotplug lte0
+iface lte0 inet dhcp
+ pre-up /usr/sbin/chat -v -f /etc/chatscripts/sunrise.HUAWEI >/dev/ttyWWAN02 /dev/ttyWWAN02 /dev/null
+
+ elif [[ $2 == off ]]; then
+ show_box "Warning" "Huawei ME909s-120 LTE will kill connection" 7
+ # enable interface
+ ifdown lte0 2> /dev/null
+ rm /etc/chatscripts/sunrise.HUAWEI
+ rm /etc/chatscripts/gsm_off.HUAWEI
+ rm /etc/network/interfaces.d/lte0
+ elif [[ $(cat /sys/class/net/lte0/operstate) == "up" ]]; then
+ LTE_MODEM="Huawei ME909s-120 LTE modem is online"
+ else
+ LTE_MODEM="Huawei ME909s-120 LTE modem is offline"
+ fi
+ ;;
+esac
+}
+
+
+
+
+#
+# check hostapd configuration. Return error or empty if o.k.
+#
+check_hostapd ()
+{
+
+ systemctl daemon-reload
+ hostapd_error=""
+ [[ -n $1 && -n $2 ]] && dialog --title " $1 " --backtitle "$BACKTITLE" --no-collapse --colors --infobox "$2" 5 $((${#2}-3))
+ service hostapd stop
+ rm -f /var/run/hostapd/*
+ sleep 1
+ service hostapd start
+ sleep 6
+ if [[ "$(hostapd_cli ping 2> /dev/null| grep PONG)" == "PONG" ]]; then
+ hostapd_error=""
+ else
+ hostapd_error=$(hostapd /etc/hostapd.conf)
+ sleep 6
+ [[ -n $(echo $hostapd_error | grep "channel") ]] && hostapd_error="channel_restriction"
+ [[ -n $(echo $hostapd_error | grep "does not support" | grep "hw_mode") ]] && hostapd_error="hw_mode"
+ [[ -n $(echo $hostapd_error | grep "not found from the channel list" | grep "802.11g") ]] && hostapd_error="wrong_channel"
+ [[ -n $(echo $hostapd_error | grep "VHT") ]] && hostapd_error="unsupported_vht"
+ [[ -n $(echo $hostapd_error | grep " HT capability") ]] && hostapd_error="unsupported_ht"
+ fi
+
+}
+
+
+
+
+#
+# check all possible wireless modes
+#
+function check_advanced_modes ()
+{
+
+ sed '/### IEEE 802.11n/,/^### IEEE 802.11n/ s/^# *//' -i /etc/hostapd.conf
+ check_hostapd "Probing" "\n802.11n \Z1(150-300Mbps)\Z0"
+ # check HT capability
+ check_ht_capab
+ if [[ -z "$hostapd_error" ]]; then
+ sed '/### IEEE 802.11a\>/,/^### IEEE 802.11a\>/ s/^# *//' -i /etc/hostapd.conf
+ sed -i "s/^channel=.*/channel=40/" /etc/hostapd.conf
+ check_hostapd "Probing" "\n802.11a \Z1(5Ghz)\Z0"
+ if [[ "$hostapd_error" == "channel_restriction" ]]; then check_channels; fi
+ if [[ "$hostapd_error" == "channel_restriction" ]]; then
+ # revering configuration
+ sed -i "s/^channel=.*/channel=5/" /etc/hostapd.conf
+ sed '/## IEEE 802.11a\>/,/^## IEEE 802.11a\>/ s/.*/#&/' -i /etc/hostapd.conf
+ check_hostapd "Reverting" "\nWireless \Z1802.11a (5Ghz)\Z0 is not supported"
+ else
+ sed '/### IEEE 802.11ac\>/,/^### IEEE 802.11ac\>/ s/^# *//' -i /etc/hostapd.conf
+ # check VHT capability
+ check_vht_capab
+ if [[ "$hostapd_error" == "unsupported_vht" || "$hostapd_error" == "channel_restriction" ]]; then
+ # revering configuration
+ sed '/## IEEE 802.11ac\>/,/^## IEEE 802.11ac\>/ s/.*/#&/' -i /etc/hostapd.conf
+ check_hostapd "Reverting" "\nWireless 802.11ac \Z1(433Mbps x n @ 5Ghz)\Z0 is not supported"
+ if [[ "$hostapd_error" == "channel_restriction" ]]; then check_channels; fi
+ fi
+ fi
+ else
+ sed '/## IEEE 802.11n/,/^## IEEE 802.11n/ s/.*/#&/' -i /etc/hostapd.conf
+ fi
+
+}
+
+
+
+
+#
+# create interface configuration section
+#
+function create_if_config() {
+
+ address=$(ip -4 addr show dev $1 | awk '/inet/ {print $2}' | cut -d'/' -f1)
+ netmask=$(ip -4 addr show dev $1 | awk '/inet/ {print $2}' | cut -d'/' -f2)
+ gateway=$(route -n | grep 'UG[ \t]' | awk '{print $2}' | sed -n '1p')
+ echo -e "# bananapi-config created"
+ echo -e "source /etc/network/interfaces.d/*\n"
+ if [[ "$3" == "fixed" ]]; then
+ echo -e "# Local loopback\nauto lo\niface lo init loopback\n"
+ echo -e "# Interface $2\nauto $2\nallow-hotplug $2"
+ echo -e "iface $2 inet static\n\taddress $address\n\tnetmask $netmask\n\tgateway $gateway\n\tdns-nameservers 8.8.8.8"
+ fi
+
+}
+
+
+
+
+#
+# reload network related services
+#
+function reload-nety() {
+
+ systemctl daemon-reload
+ if [[ "$1" == "reload" ]]; then WHATODO="Reloading services"; else WHATODO="Stopping services"; fi
+ (service network-manager stop >/dev/null 2>&1; service NetworkManager stop >/dev/null 2>&1; echo 10; sleep 1; service hostapd stop; echo 20; sleep 1; service dnsmasq stop; echo 30; sleep 1;\
+ [[ "$1" == "reload" ]] && service dnsmasq start && echo 60 && sleep 1 && service hostapd start && echo 80 && sleep 1;\
+ service network-manager start >/dev/null 2>&1; service NetworkManager start >/dev/null 2>&1; echo 90; sleep 5;) | dialog --backtitle "$BACKTITLE" --title " $WHATODO " --gauge "" 6 70 0
+ systemctl restart systemd-resolved.service
+
+}
+
+
+
+
+#
+# Check if something is running on port $1 and display info
+#
+function check_port ()
+{
+ [[ -n $(netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".'$1'"') ]] && dialog --backtitle "$BACKTITLE" --title "Checking service" \
+ --msgbox "\nIt looks good.\n\nThere is $2 service on port $1" 9 52
+}
+
+
+
+
+#
+# check wifi high throughput
+#
+function check_ht_capab ()
+{
+ declare -a arr=("[HT40+][LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40][SMPS-STATIC]" \
+ "[HT40-][SHORT-GI-40][SHORT-GI-40][DSSS_CCK-40]" "[SHORT-GI-20][SHORT-GI-40][HT40+]" "[DSSS_CK-40][HT20+]" "")
+ local j=0
+ for i in "${arr[@]}"
+ do
+ j=$((j+(100/${#arr[@]})))
+ echo $j | dialog --title " Probing HT " --colors --gauge "\nSeeking for optimal \Z1high throughput\Z0 settings." 8 50 0
+ sed -i "s/^ht_capab=.*/ht_capab=$i/" /etc/hostapd.conf
+ check_hostapd
+ if [[ "$hostapd_error" == "channel_restriction" ]]; then check_channels; fi
+ if [[ "$hostapd_error" == "" ]]; then break; fi
+ done
+}
+
+
+
+
+#
+# check wifi high throughput
+#
+function check_vht_capab ()
+{
+
+ declare -a arr=("[MAX-MPDU-11454][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP3]" "[MAX-MPDU-11454][SHORT-GI-80][RX-STBC-1][MAX-A-MPDU-LEN-EXP3]" "")
+ local j=0
+ for i in "${arr[@]}"
+ do
+ j=$((j+(100/${#arr[@]})))
+ echo $j | dialog --title " Probing VHT " --colors --gauge "\nSeeking for optimal \Z1very high throughput\Z0 settings." 8 54 0
+ sed -i "s/^vht_capab=.*/vht_capab=$i/" /etc/hostapd.conf
+ check_hostapd
+ if [[ "$hostapd_error" == "channel_restriction" ]]; then check_channels; fi
+ if [[ "$hostapd_error" == "" ]]; then break; fi
+ done
+
+}
+
+
+
+
+#
+# check 5Ghz channels
+#
+function check_channels ()
+{
+
+ declare -a arr=("36" "40")
+ for i in "${arr[@]}"
+ do
+ sed -i "s/^channel=.*/channel=$i/" /etc/hostapd.conf
+ check_hostapd "Probing" "\nChannel:\Z1 ${i}\Z0"
+ if [[ "$hostapd_error" != "channel_restriction" ]]; then break; fi
+ done
+
+}
+
+
+#
+# convert netmask to CIDR
+#
+function netmask_to_cidr ()
+{
+ IFS=' '
+ local bits=0
+ for octet in $(echo $1| sed 's/\./ /g'); do
+ binbits=$(echo "obase=2; ibase=10; ${octet}"| bc | sed 's/0//g')
+ let bits+=${#binbits}
+ done
+ echo "${bits}"
+}
+
+
+#
+# edit ip address within network manager
+#
+function nm_ip_editor ()
+{
+
+exec 3>&1
+ dialog --title " Static IP configuration" --backtitle "$BACKTITLE" --form "\nAdapter: $1
+ \n " 12 38 0 \
+ "Address:" 1 1 "$address" 1 15 15 0 \
+ "Netmask:" 2 1 "$netmask" 2 15 15 0 \
+ "Gateway:" 3 1 "$gateway" 3 15 15 0 \
+ 2>&1 1>&3 | {
+ read -r address;read -r netmask;read -r gateway
+ if [[ $? = 0 ]]; then
+ localuuid=$(LC_ALL=C nmcli -f UUID,DEVICE connection show | grep $1 | awk '{print $1}')
+ # convert netmask value to CIDR if required
+ if [[ $netmask =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
+ CIDR=$(netmask_to_cidr ${netmask})
+ else
+ CIDR=${netmask}
+ fi
+ if [[ -n "$localuuid" ]]; then
+ # adjust existing
+ nmcli con mod $localuuid ipv4.method manual ipv4.addresses "$address/$CIDR" >/dev/null 2>&1
+ nmcli con mod $localuuid ipv4.method manual ipv4.gateway "$gateway" >/dev/null 2>&1
+ nmcli con mod $localuuid ipv4.dns "8.8.8.8,$gateway" >/dev/null 2>&1
+ nmcli con down $localuuid >/dev/null 2>&1
+ sleep 2
+ nmcli con up $localuuid >/dev/null 2>&1
+ else
+ # create new
+ nmcli con add con-name "bananapi" ifname "$1" type 802-3-ethernet ip4 "$address/$CIDR" gw4 "$gateway" >/dev/null 2>&1
+ nmcli con mod "bananapi" ipv4.dns "8.8.8.8,$gateway" >/dev/null 2>&1
+ nmcli con up "bananapi" >/dev/null 2>&1
+ fi
+ fi
+ }
+}
+
+
+
+
+#
+# edit ip address
+#
+function systemd_ip_editor ()
+{
+
+ local filename="/etc/systemd/network/10-$1.network"
+ if [[ -f $filename ]]; then
+ sed -i '/Network/,$d' $filename
+ exec 3>&1
+ dialog --title " Static IP configuration" --backtitle "$BACKTITLE" --form "\nAdapter: $1
+ \n " 12 38 0 \
+ "Address:" 1 1 "$address" 1 15 15 0 \
+ "Netmask:" 2 1 "$netmask" 2 15 15 0 \
+ "Gateway:" 3 1 "$gateway" 3 15 15 0 \
+ 2>&1 1>&3 | {
+ read -r address;read -r netmask;read -r gateway
+ if [[ $? = 0 ]]; then
+ echo -e "[Network]" >>$filename
+ echo -e "Address=$address" >> $filename
+ echo -e "Gateway=$gateway" >> $filename
+ echo -e "DNS=8.8.8.8" >> $filename
+ fi
+ }
+ fi
+
+}
+
+
+
+
+#
+# edit ip address
+#
+function ip_editor ()
+{
+
+ exec 3>&1
+ dialog --title " Static IP configuration" --backtitle "$BACKTITLE" --form "\nAdapter: $1
+ \n " 12 38 0 \
+ "Address:" 1 1 "$address" 1 15 15 0 \
+ "Netmask:" 2 1 "$netmask" 2 15 15 0 \
+ "Gateway:" 3 1 "$gateway" 3 15 15 0 \
+ 2>&1 1>&3 | {
+ read -r address;read -r netmask;read -r gateway
+ if [[ $? = 0 ]]; then
+ echo -e "# bananapi-config created\nsource /etc/network/interfaces.d/*\n" >$3
+ echo -e "# Local loopback\nauto lo\niface lo inet loopback\n" >> $3
+ echo -e "# Interface $2\nauto $2\nallow-hotplug $2\niface $2 inet static\
+ \n\taddress $address\n\tnetmask $netmask\n\tgateway $gateway\n\tdns-nameservers 8.8.8.8" >> $3
+ fi
+ }
+
+}
+
+
+
+
+#
+# edit hostapd parameters
+#
+function wlan_edit_basic ()
+{
+ source /etc/hostapd.conf
+ exec 3>&1
+ dialog --title "AP configuration" --backtitle "$BACKTITLE" --form "\nWPA2 enabled, \
+ advanced config: edit /etc/hostapd.conf\n " 12 58 0 \
+ "SSID:" 1 1 "$ssid" 1 31 22 0 \
+ "Password:" 2 1 "$wpa_passphrase" 2 31 22 0 \
+ "Channel:" 3 1 "$channel" 3 31 3 0 \
+ 2>&1 1>&3 | {
+ read -r ssid;read -r wpa_passphrase;read -r channel
+ if [[ $? = 0 ]]; then
+ sed -i "s/^ssid=.*/ssid=$ssid/" /etc/hostapd.conf
+ sed -i "s/^wpa_passphrase=.*/wpa_passphrase=$wpa_passphrase/" /etc/hostapd.conf
+ sed -i "s/^channel=.*/channel=$channel/" /etc/hostapd.conf
+ wpa_psk=$(wpa_passphrase $ssid $wpa_passphrase | grep '^[[:blank:]]*[^[:blank:]#;]' | grep psk | cut -d= -f2-)
+ sed -i "s/^wpa_psk=.*/wpa_psk=$wpa_psk/" /etc/hostapd.conf
+ fi
+ }
+}
+
+
+
+
+#
+# edit hostapd parameters
+#
+function wlan_edit ()
+{
+
+ # select default interfaces if there is more than one
+ select_interface "default"
+ dialog --title " Configuration edit " --colors --backtitle "$BACKTITLE" --help-button --help-label "Cancel" --yes-label "Basic" \
+ --no-label "Advanced" --yesno "\n\Z1Basic:\Z0 Change SSID, password and channel\n\n\Z1Advanced:\Z0 Edit /etc/hostapd.conf file" 9 70
+ if [[ $? = 0 ]]; then
+ wlan_edit_basic
+ elif [[ $? = 1 ]]; then
+ dialog --backtitle "$BACKTITLE" --title " Edit hostapd configuration /etc/hostapd.conf" --no-collapse \
+ --ok-label "Save" --editbox /etc/hostapd.conf 30 0 2> /etc/hostapd.conf.out
+ [[ $? = 0 ]] && mv /etc/hostapd.conf.out /etc/hostapd.conf && service hostapd restart
+ fi
+
+}
+
+
+
+
+#
+# here we add wifi exceptions
+#
+function wlan_exceptions ()
+{
+
+ reboot_module=false
+ [[ -n "$(lsmod | grep -w dhd)" && $1 = "on" ]] && \
+ echo 'options dhd op_mode=2' >/etc/modprobe.d/ap6212.conf && rmmod dhd && modprobe dhd
+ [[ -n "$(lsmod | grep -w dhd)" && $1 = "off" ]] && \
+ rm /etc/modprobe.d/ap6212.conf && rmmod dhd && modprobe dhd
+ # Cubietruck
+ [[ -n "$(lsmod | grep -w ap6210)" && $1 = "on" ]] && \
+ echo 'options ap6210 op_mode=2' >/etc/modprobe.d/ap6210.conf && reboot_module=true
+ [[ -n "$(lsmod | grep -w ap6210)" && $1 = "off" ]] && \
+ rm /etc/modprobe.d/ap6210.conf && reboot_module=true
+
+}
+
+
+
+
+#
+# here add shaddy wifi adaptors
+#
+function check_and_warn ()
+{
+
+ local shaddy=false
+ # blacklist
+ [[ -n "$(lsmod | grep mt7601u)" ]] && shaddy=true
+ [[ -n "$(lsmod | grep r8188eu)" ]] && shaddy=true
+ # blacklist
+ if [[ "$shaddy" == "true" ]]; then
+ dialog --title " Warning " --ok-label " Accept and proceed " --msgbox '\nOne of your wireless drivers are on a black list due to poor quality.\n\nAP mode might not be possible!' 9 73
+ fi
+
+}
+
+
+
+
+#
+# search for wlan interfaces and provide a selection menu if there are more than one
+#
+function get_wlan_interface ()
+{
+
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+
+ WLAN_INTERFACES=($(LC_ALL=C nmcli --wait 10 dev status | grep wifi | grep disconnected |awk '{print $1}'))
+ local LIST=()
+ for i in "${WLAN_INTERFACES[@]}"
+ do
+ LIST+=( "${i[0]//[[:blank:]]/}" "" )
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+
+ if [ "$LIST_LENGTH" -eq 1 ]; then
+ WIRELESS_ADAPTER=${WLAN_INTERFACES[0]}
+ else
+ exec 3>&1
+ WIRELESS_ADAPTER=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select wlan interface" --clear --menu "" $((6+${LIST_LENGTH})) 40 15 "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+
+}
+
+
+
+
+function select_interface ()
+{
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+ local ADAPTER=($(nmcli device status | grep ethernet | awk '{ print $1 }' | grep -v lo))
+ local LIST=()
+ for i in "${ADAPTER[@]}"
+ do
+ local IPADDR=$(LC_ALL=C ip -4 addr show dev ${i[0]} | awk '/inet/ {print $2}' | cut -d'/' -f1)
+ ADD_SPEED=""
+ [[ $i == eth* || $i == en* ]] && ADD_SPEED=$(ethtool $i | grep Speed)
+ [[ $i == wl* ]] && ADD_SPEED=$(LC_ALL=C nmcli -f RATE,DEVICE,ACTIVE dev wifi list | grep $i | grep yes | awk 'NF==4{print $1""$2}NF==1' | sed -e 's/^/ Speed: /' | tail -1)
+ LIST+=( "${i[0]//[[:blank:]]/}" "${IPADDR} ${ADD_SPEED}" )
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ if [ "$LIST_LENGTH" -eq 0 ]; then
+ SELECTED_ADAPTER="lo"
+ elif [ "$LIST_LENGTH" -eq 1 ]; then
+ SELECTED_ADAPTER=${ADAPTER[0]}
+ else
+ exec 3>&1
+ SELECTED_ADAPTER=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse --title "Select $1 interface" --clear \
+ --menu "" $((6+${LIST_LENGTH})) 74 14 "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+
+}
+
+
+
+
+#
+# select interface if there is more than one and adjust metric
+#
+# $1 = default | all
+#
+function select_default_interface ()
+{
+
+ ALREADY_DEFINED=$(cat /etc/iptables.ipv4.nat 2> /dev/null | grep "POSTROUTING -o" | tail -1 | awk '{ print $4 }')
+ if [[ -n "${ALREADY_DEFINED}" ]]; then
+ DEFAULT_ADAPTER=${ALREADY_DEFINED}
+ else
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+ if [[ $1 == "default" ]]; then
+ local ADAPTER=($(nmcli -t -f DEVICE connection show --active))
+ else
+ local ADAPTER=($(nmcli device status | tail -n +2 | awk '{ print $1 }' | grep -v lo))
+ fi
+ local LIST=()
+ for i in "${ADAPTER[@]}"
+ do
+ local IPADDR=$(LC_ALL=C ip -4 addr show dev ${i[0]} | awk '/inet/ {print $2}' | cut -d'/' -f1)
+ ADD_SPEED=""
+ [[ $i == eth* || $i == en* ]] && ADD_SPEED=$(ethtool $i | grep Speed)
+ [[ $i == wl* ]] && ADD_SPEED=$(LC_ALL=C nmcli -f RATE,DEVICE,ACTIVE dev wifi list | grep $i | grep yes | awk 'NF==4{print $1""$2}NF==1' | sed -e 's/^/ Speed: /' | tail -1)
+ if [[ $1 == "default" ]]; then
+ [[ $IPADDR != "172.24.1.1" && -n $IPADDR ]] && LIST+=( "${i[0]//[[:blank:]]/}" "${IPADDR} ${ADD_SPEED}" )
+ else
+ [[ $IPADDR != "172.24.1.1" ]] && LIST+=( "${i[0]//[[:blank:]]/}" "${IPADDR} ${ADD_SPEED}" )
+ fi
+ done
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ if [ "$LIST_LENGTH" -eq 0 ]; then
+ DEFAULT_ADAPTER="lo"
+ elif [ "$LIST_LENGTH" -eq 1 ]; then
+ DEFAULT_ADAPTER=${ADAPTER[0]}
+ else
+ exec 3>&1
+ DEFAULT_ADAPTER=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \
+ --title "Select default interface" --clear --menu "" $((6+${LIST_LENGTH})) 74 14 "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ fi
+ fi
+
+ # set highest metric to default adaptor
+ HIGHEST_METRIC=$(nmcli -t -f UUID,TYPE,DEVICE connection show --active | grep $DEFAULT_ADAPTER | sed 's/:.*$//')
+
+ # set metric to 50
+ nmcli connection modify $HIGHEST_METRIC ipv4.route-metric 50 2> /dev/null
+
+ METRIC=77
+ # set others wired
+ REMAINING=( `nmcli -t -f UUID,TYPE,DEVICE connection show --active | grep ethernet | grep -v $DEFAULT_ADAPTER | sed 's/:.*$//'` )
+ if [[ ${#REMAINING[@]} -ge 1 ]]; then
+ for i in "${REMAINING[@]}"
+ do
+ METRIC=$(( $METRIC + 1 ))
+ nmcli connection modify ${i} ipv4.route-metric $METRIC
+ done
+ fi
+
+ # set other wireless
+ METRIC=88
+ REMAINING=( `nmcli -t -f UUID,TYPE,DEVICE connection show --active | grep wireless | grep -v $DEFAULT_ADAPTER | sed 's/:.*$//'` )
+ if [[ ${#REMAINING[@]} -ge 1 ]]; then
+ for i in "${REMAINING[@]}"
+ do
+ METRIC=$(( $METRIC + 1 ))
+ nmcli connection modify ${i} ipv4.route-metric $METRIC
+ done
+ fi
+
+ # create default metrics file
+ cat <<-EOF > /etc/NetworkManager/conf.d/bananapi-default-metric.conf
+ [connection-ethernet-gateway]
+ match-device=interface-name:$DEFAULT_ADAPTER
+ ipv4.route-metric=50
+
+ [connection-wifi-other]
+ match-device=type:wifi
+ ipv4.route-metric=88
+
+ [connection-ethernet-other]
+ match-device=type:ethernet
+ ipv4.route-metric=77
+EOF
+}
+
+
+
+
+#
+# search and connect to Bluetooth devices
+#
+function connect_bt_interface ()
+{
+
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+ dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nDiscovering Bluetooth devices ... " 5 37
+ BT_INTERFACES=($(hcitool scan | sed '1d'))
+
+ local LIST=()
+ for i in "${BT_INTERFACES[@]}"
+ do
+ local a=$(echo ${i[0]//[[:blank:]]/} | sed -e 's/^\(.\{17\}\).*/\1/')
+ local b=${i[0]//$a/}
+ local b=$(echo $b | sed -e 's/^[ \t]*//')
+ LIST+=( "$a" "$b")
+ done
+
+ LIST_LENGTH=$((${#LIST[@]}/2));
+ if [ "$LIST_LENGTH" -eq 0 ]; then
+ BT_ADAPTER=${WLAN_INTERFACES[0]}
+ dialog --backtitle "$BACKTITLE" --title "Bluetooth" --msgbox "\nNo nearby Bluetooth devices were found!" 7 43
+ else
+ exec 3>&1
+ BT_ADAPTER=$(dialog --backtitle "$BACKTITLE" --no-collapse --title "Select interface" \
+ --clear --menu "" $((6+${LIST_LENGTH})) 50 15 "${LIST[@]}" 2>&1 1>&3)
+ exec 3>&-
+ if [[ $BT_ADAPTER != "" ]]; then
+ dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nConnecting to $BT_ADAPTER " 5 35
+ BT_EXEC=$(
+ expect -c 'set prompt "#";set address '$BT_ADAPTER';spawn bluetoothctl;expect -re $prompt;send "disconnect $address\r";
+ sleep 1;send "remove $address\r";sleep 1;expect -re $prompt;send "scan on\r";sleep 8;send "scan off\r";
+ expect "Controller";send "trust $address\r";sleep 2;send "pair $address\r";sleep 2;send "connect $address\r";
+ send_user "\nShould be paired now.\r";sleep 2;send "quit\r";expect eof')
+ echo "$BT_EXEC" > /tmp/bt-connect-debug.log
+ if [[ $(echo "$BT_EXEC" | grep "Connection successful" ) != "" ]]; then
+ dialog --backtitle "$BACKTITLE" --title "Bluetooth" --msgbox "\nYour device is ready to use!" 7 32
+ else
+ dialog --backtitle "$BACKTITLE" --title "Bluetooth" --msgbox "\nError connecting. Try again!" 7 32
+ fi
+ fi
+ fi
+
+}
diff --git a/external/cache/sources/bananapi-config/debian-config-jobs b/external/cache/sources/bananapi-config/debian-config-jobs
new file mode 100644
index 0000000..36739d2
--- /dev/null
+++ b/external/cache/sources/bananapi-config/debian-config-jobs
@@ -0,0 +1,1583 @@
+#!/bin/bash
+#
+#
+# Copyright (c) 2017 Igor Pecovnik, igor.pecovnik@gma**.com
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+[[ -n ${SUDO_USER} ]] && SUDO="sudo "
+
+function jobs ()
+{
+ # Shows box with loading ...
+ #
+ dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nLoading ${selection,,} submodule ... " 5 $((26+${#selection}))
+
+ unset selection
+
+ case $1 in
+
+ #-------------------------------------------------------------------------------------------------------------------------------------#
+
+
+ # Application installer
+ #
+ "Softy" )
+ [[ -f softy ]] && ./softy || softy
+ ;;
+
+ # Remove BT
+ #
+ "BT remove" )
+ if ! is_package_manager_running; then
+ debconf-apt-progress -- apt-get -y remove bluetooth bluez bluez-tools
+ check_if_installed xserver-xorg && debconf-apt-progress -- apt-get -y remove pulseaudio-module-bluetooth blueman
+ debconf-apt-progress -- apt -y -qq autoremove
+ fi
+ ;;
+
+ # Enabling BT
+ #
+ "BT install" )
+ if ! is_package_manager_running; then
+ debconf-apt-progress -- apt-get -y install bluetooth bluez bluez-tools
+ check_if_installed xserver-xorg && debconf-apt-progress -- apt-get -y --no-install-recommends install pulseaudio-module-bluetooth blueman
+ fi
+ ;;
+
+ # Removing IR
+ #
+ "Remove IR" )
+ if ! is_package_manager_running; then
+ debconf-apt-progress -- apt-get -y remove lirc
+ debconf-apt-progress -- apt -y -qq autoremove
+ fi
+ ;;
+
+ # Enabling IR
+ #
+ "IR" )
+ if ! is_package_manager_running; then
+ debconf-apt-progress -- apt-get -y --no-install-recommends install lirc
+ fi
+ ;;
+
+
+ # Sharing USB ports
+ #
+ "USB redirector" )
+ if [[ -n $(netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".'32032'"') ]]; then
+ [[ -f /usr/local/usb-redirector/uninstall.sh ]] && /usr/local/usb-redirector/uninstall.sh uninstall
+ rm -f /usr/local/bin/usbclnt
+ else
+ TARGET_BRANCH=$BRANCH
+ exceptions "$BRANCH"
+ IFS='.' read -a array <<< $(uname -r)
+ [[ -z $(dpkg -l | grep linux-headers) ]] && debconf-apt-progress -- apt-get -y \
+ install linux-headers${TARGET_BRANCH}-${TARGET_FAMILY}
+ if (( "${array[0]}" == "4" )) && (( "${array[1]}" >= "1" )); then
+ rm -rf /usr/src/usb-redirector-linux-arm-gnueabi
+ wget -qO- https://www.incentivespro.com/usb-redirector-linux-arm-gnueabi.tar.gz | tar xz -C /usr/src
+ cd /usr/src/usb-redirector-linux-arm-gnueabi/
+ else
+ rm -rf /usr/src/usb-redirector-linux-arm-eabi
+ wget -qO- https://raw.githubusercontent.com/armbian/build/master/packages/blobs/usb-redirector/usb-redirector-old.tgz \
+ | tar xz -C /usr/src
+ cd /usr/src/usb-redirector-linux-arm-eabi/
+ fi
+ ./installer.sh install
+ sleep 3
+ check_port "32032" "USB Redirector"
+ fi
+ ;;
+
+
+ # Simple CLI monitoring
+ #
+ "Monitor" )
+ clear
+ bananapimonitor -m
+ sleep 2
+ ;;
+
+
+ # SBC-becn
+ #
+ "Benchmarking" )
+ if [[ ! -f /usr/local/bin/sbc-bench ]]; then
+ wget -q -O /usr/local/bin/sbc-bench https://gitee.com/leeboby/sbc-bench/raw/master/sbc-bench.sh
+
+ if [[ -z "$(command -v git)" ]]; then
+ sudo apt-get update
+ sudo apt-get install -y git
+ fi
+
+ chmod +x /usr/local/bin/sbc-bench
+ fi
+ sbc-bench
+ echo ""
+ read -n 1 -s -p "Press any key to continue"
+ ;;
+
+
+ # Send diagnostics
+ #
+ "Diagnostics" )
+ clear
+ bananapimonitor -u
+ echo ""
+ read -n 1 -s -p "Press any key to continue"
+ ;;
+
+
+ # Control board consumption
+ #
+ "Consumption" )
+ clear
+ h3consumption
+ echo -e "\nType \e[92m${SUDO}${0##*/}\e[0m to get back\n"
+ exit
+ ;;
+
+
+ # Board (fex) settings editor
+ #
+ "Fexedit" )
+ exec 3>&1
+ monitor=$(dialog --print-maxsize 2>&1 1>&3)
+ exec 3>&-
+ mon_x=$(echo $monitor | awk '{print $2}' | sed 's/,//')
+ mon_y=$(echo $monitor | awk '{print $3}' | sed 's/,//')
+ TEMP=$(mktemp -d || exit 1)
+ trap "rm -rf \"${TEMP}\" ; exit 0" 0 1 2 3 15
+ bin2fex /boot/script.bin ${TEMP}/tempfex.txt >/dev/null 2>&1
+ dialog --title "Edit u-boot environment" \
+ --ok-label "Save" --no-collapse --editbox ${TEMP}/tempfex.txt $mon_y 0 2> ${TEMP}/tempfex.out
+ [[ $? = 0 ]] && fex2bin ${TEMP}/tempfex.out /boot/script.bin
+ ;;
+
+
+
+
+ #
+ # Install kernel headers
+ #
+ "Headers_install" )
+ if ! is_package_manager_running; then
+ if [[ -f /etc/bananapi-release ]]; then
+ INSTALL_PKG="linux-headers-${BRANCH}-${LINUXFAMILY}";
+ else
+ INSTALL_PKG="linux-headers-$(uname -r | sed 's/'-$(dpkg --print-architecture)'//')";
+ fi
+ debconf-apt-progress -- apt-get -y install ${INSTALL_PKG}
+ fi
+ ;;
+
+
+ #
+ # Remove kernel headers
+ #
+ "Headers_remove" )
+ if ! is_package_manager_running; then
+ REMOVE_PKG="linux-headers-*"
+ if [[ -n $(dpkg -l | grep linux-headers) ]]; then
+ debconf-apt-progress -- apt-get -y purge ${REMOVE_PKG}
+ rm -rf /usr/src/linux-headers*
+ else
+ debconf-apt-progress -- apt-get -y install ${INSTALL_PKG}
+ fi
+ # cleanup
+ apt clean
+ debconf-apt-progress -- apt -y autoremove
+ fi
+ ;;
+
+
+ #
+ # Install kernel source
+ #
+ "Source_install" )
+ if ! is_package_manager_running; then
+
+ if [[ -z $scripted ]]; then
+ LIST=()
+ for pkg in $SOURCE_PKG_LIST
+ do
+ LIST+=( "$pkg" "" )
+ done
+
+ exec 3>&1
+ selection=$(dialog --backtitle "$BACKTITLE" --title "Kernel install" --clear --cancel-label "Back" \
+ --menu "Choose kernel version" 12 70 ${#LIST[@]} "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ [[ $exit_status == 1 || $exit_status == 255 ]] && clear
+ else
+ selection=$(echo $SOURCE_PKG_LIST | awk '{ print $NF }')
+ fi
+
+ PACKAGE=$(echo "$selection" | sed "s/-current//" | sed "s/-dev//" | sed "s/-legacy//")
+ if [[ -n $PACKAGE ]]; then
+ debconf-apt-progress -- apt-get -y install ${selection}
+ mkdir -p /usr/src/$PACKAGE
+ (pv -n /usr/src/$PACKAGE".tar.xz" | xz -d -T0 - | tar xf - -C /usr/src/$PACKAGE ) 2>&1 | dialog --colors --backtitle "$BACKTITLE" --title " Please wait! " --gauge "\nDecompressing kernel sources to /usr/src/$PACKAGE" 8 80
+ xz -d /usr/src/*config.xz --stdout > /usr/src/$PACKAGE/.config
+ rm /usr/src/$PACKAGE".tar.xz" /usr/src/*config.xz
+ apt clean
+ debconf-apt-progress -- apt-get -y purge linux-source*
+ debconf-apt-progress -- apt -y autoremove
+ if [[ -z $scripted ]]; then
+ dialog --colors --backtitle "$BACKTITLE" --no-collapse --title " Kernel source " --clear --msgbox "\nYou will find pre-configured kernel sources in /usr/src/$PACKAGE" 7 72
+ fi
+ else
+ dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nLoading software submodule ... " 5 34
+ fi
+ fi
+ ;;
+
+
+
+ #
+ # Remove kernel source
+ #
+ "Source_remove" )
+ if ! is_package_manager_running; then
+
+ if [[ -z $scripted ]]; then
+ LIST=()
+ for pkg in $SOURCE_PKG_LIST_INSTALLED
+ do
+ LIST+=( "$pkg" "" )
+ done
+
+ exec 3>&1
+ selection=$(dialog --backtitle "$BACKTITLE" --title "Kernel remove" --clear --cancel-label "Back" \
+ --menu "Choose kernel version" 12 70 ${#LIST[@]} "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ [[ $exit_status == 1 || $exit_status == 255 ]] && clear
+ else
+ selection=$(echo $SOURCE_PKG_LIST_INSTALLED | awk '{ print $NF }')
+ fi
+
+ if [[ -n $selection ]]; then
+ PACKAGE="linux-source-$(echo $selection | sed 's/[-|(|[:alpha:]|(|[:space:]|(|/]//g')-${BRANCH}-${LINUXFAMILY}"
+ if ls $selection 1> /dev/null 2>&1; then
+ debconf-apt-progress -- apt-get -y purge $PACKAGE
+ debconf-apt-progress -- apt -y autoremove
+ apt clean
+ dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nRemoving $selection ... " 5 72
+ rm -r $selection
+ fi
+ if [[ -z $scripted ]]; then
+ dialog --colors --backtitle "$BACKTITLE" --no-collapse --title " Kernel source " --clear --msgbox "\n$selection removed" 7 72
+ fi
+ else
+ dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nLoading software submodule ... " 5 34
+ fi
+ fi
+ ;;
+
+
+
+ # Toggle mini and full firmware
+ #
+ "Full"|"Mini" )
+ if ! is_package_manager_running; then
+ debconf-apt-progress -- apt-get -y purge bananapi-firmware* # workaround since pkg replace doesn't work properly
+ debconf-apt-progress -- apt-get -y install bananapi-firmware$(echo -"${1,,}" | sed 's/-mini//')
+ fi
+ ;;
+
+
+ # Set the display resolution
+ #
+ "Display" )
+ # show display modes menu
+ if [[ -f /usr/bin/h3disp ]]; then
+ # h3 boards
+ get_h3modes
+ dialog --title " Display output type " --colors --help-button --help-label "Cancel" --no-label "DVI" --yes-label "HDMI" \
+ --backtitle "$BACKTITLE" --yesno "\nIn case you use an HDMI-to-DVI converter choose DVI!" 7 57
+ output_type=$?
+ if [[ $output_type = 0 || $output_type = 1 ]]; then
+ if [[ $output_type = 0 ]]; then
+ display_cmd="h3disp -m $SCREEN_RESOLUTION";
+ else
+ display_cmd="h3disp -m $SCREEN_RESOLUTION -d";
+ fi
+
+
+ fi
+ elif [[ "$LINUXFAMILY" = odroidc* || "$LINUXFAMILY" = odroidn2 ]]; then
+ get_odroidmodes
+ display_cmd="sed -i \"s/^setenv m .*/# &/\" /boot/boot.ini;sed -i '/setenv m \"$SCREEN_RESOLUTION\"/s/^# //g' /boot/boot.ini";
+ # odroid n2
+ display_cmd='sed -i "s/^setenv hdmimode .*/setenv hdmimode \"$SCREEN_RESOLUTION\"/" /boot/boot.ini; sed -i "s/^setenv display_autodetect .*/setenv display_autodetect \"false\"/" /boot/boot.ini';
+ else
+ # a20 boards
+ get_a20modes
+ display_cmd="sed -i \"s/^disp_mode=.*/disp_mode=$SCREEN_RESOLUTION/\" /boot/bananapiEnv.txt";
+ fi
+
+ dialog --title " Display resolution " --colors --no-label "Cancel" --backtitle "$BACKTITLE" --yesno \
+ "\nSwitching to \Z1$SCREEN_RESOLUTION\Z0 and reboot?" 7 42
+ if [[ $? = 0 ]]; then
+ eval $display_cmd > /dev/null
+ reboot
+ fi
+ ;;
+
+
+ #-------------------------------------------------------------------------------------------------------------------------------------#
+ #-------------------------------------------------------------------------------------------------------------------------------------#
+ #-------------------------------------------------------------------------------------------------------------------------------------#
+
+
+
+ # Select dynamic or edit static IP address
+ #
+ "IP" )
+ select_interface
+ # check if we have systemd networking in action
+ SYSTEMDNET=$(service systemd-networkd status | grep -w active | grep -w running)
+ dialog --title " IP address assignment " --colors --backtitle "$BACKTITLE" --help-button --help-label "Cancel" \
+ --yes-label "DHCP" --no-label "Static" --yesno \
+ "\n\Z1DHCP:\Z0 automatic IP assignment by your router or DHCP server\n\n\Z1Static:\Z0 manually fixed IP address" 9 70
+ exitstatus=$?;
+
+ # dynamic
+ if [[ $exitstatus = 0 ]]; then
+ if [[ -n $SYSTEMDNET ]]; then
+ filename="/etc/systemd/network/10-${SELECTED_ADAPTER}.network"
+ if [[ -f $filename ]]; then
+ sed -i '/Network/,$d' $filename
+ echo -e "[Network]" >>$filename
+ echo -e "DHCP=ipv4" >>$filename
+ fi
+ else
+ if [[ -n $(LC_ALL=C nmcli device status | grep $SELECTED_ADAPTER ) ]]; then
+ nmcli connection delete uuid $(LC_ALL=C nmcli -f UUID,DEVICE connection show | grep $SELECTED_ADAPTER | awk '{print $1}') >/dev/null 2>&1
+ nmcli con add con-name "Orange Pi ethernet" type ethernet ifname $SELECTED_ADAPTER >/dev/null 2>&1
+ nmcli con up "Orange Pi ethernet" >/dev/null 2>&1
+ else
+ create_if_config "$SELECTED_ADAPTER" "$SELECTED_ADAPTER" "dynamic" > /etc/network/interfaces
+ fi
+ fi
+ fi
+
+ # static
+ if [[ $exitstatus = 1 ]]; then
+ create_if_config "$SELECTED_ADAPTER" "$SELECTED_ADAPTER" "fixed" > /dev/null
+ if [[ -n $SYSTEMDNET ]]; then
+ systemd_ip_editor "${SELECTED_ADAPTER}"
+ else
+ if [[ -n $(LC_ALL=C nmcli device status | grep $SELECTED_ADAPTER ) ]]; then
+ nm_ip_editor "$SELECTED_ADAPTER"
+ else
+ ip_editor "$SELECTED_ADAPTER" "$SELECTED_ADAPTER" "/etc/network/interfaces"
+ fi
+ fi
+ fi
+ ;;
+
+ # Start network performance daemon
+ #
+ "Iperf3" )
+ #
+ if pgrep -x "iperf3" > /dev/null
+ then
+ pkill iperf3
+ else
+ iperf3 -s -D
+ fi
+ ;;
+
+
+ # Toggle IPv6
+ #
+ "IPV6" )
+ #
+ sed -i --follow-symlinks '/^net.ipv6.conf*/d' /etc/sysctl.d/99-sysctl.conf
+ if [ -f "/etc/apt/apt.conf.d/99force-ipv4" ]; then
+ rm /etc/apt/apt.conf.d/99force-ipv4
+ echo 'net.ipv6.conf.all.disable_ipv6 = 0' >> /etc/sysctl.d/99-sysctl.conf
+ echo 'net.ipv6.conf.default.disable_ipv6 = 0' >> /etc/sysctl.d/99-sysctl.conf
+ echo 'net.ipv6.conf.lo.disable_ipv6 = 0' >> /etc/sysctl.d/99-sysctl.conf
+ else
+ echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99force-ipv4
+ echo 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.d/99-sysctl.conf
+ echo 'net.ipv6.conf.default.disable_ipv6 = 1' >> /etc/sysctl.d/99-sysctl.conf
+ echo 'net.ipv6.conf.lo.disable_ipv6 = 1' >> /etc/sysctl.d/99-sysctl.conf
+ fi
+ sysctl -p > /dev/null
+ ;;
+
+
+ # Connect to wireless access point
+ #
+ "WiFi" )
+ # disable AP mode on certain adapters
+ wlan_exceptions "off"
+ [[ "$reboot_module" == true ]] && dialog --backtitle "$BACKTITLE" --title " Warning " --msgbox "\nReboot is required for this adapter to switch to STA mode" 7 62 && reboot
+ nmtui-connect
+ ;;
+
+
+ # Connect to 3G/4G network
+ #
+ "LTE" )
+ if ! is_package_manager_running; then
+ if [[ $LTE_MODEM == *online* ]]; then
+ dialog --title " LTE modem is connected " --colors --backtitle "$BACKTITLE" --yes-label "Back" --no-label "Disconnect" --yesno "\n\Z1Disconnect:\Z0 kill mobile connection\n\n" 7 42
+ [[ $? = 1 ]] && lte "$LTE_MODEM_ID" "off"
+ else
+ dialog --title " LTE modem is disconnected " --colors --backtitle "$BACKTITLE" --yes-label "Back" --no-label "Connect" --yesno "\n\Z1Connect:\Z0 dial mobile connection\n\n" 7 42
+ [[ $? = 1 ]] && lte "$LTE_MODEM_ID" "on"
+ fi
+ fi
+ ;;
+
+
+ # Connect to wireless access point
+ #
+ "Clear" )
+ # remove managed interfaces
+ systemctl daemon-reload
+ nmcli con delete $(nmcli --fields NAME,UUID,TYPE con | grep wifi | awk '{print $2}')
+ sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ rm -f /etc/network/interfaces.d/bananapi.ap.*
+ rm -f /etc/dnsmasq.conf
+ systemctl stop dnsmasq
+ systemctl disable dnsmasq
+ iptables -t nat -D POSTROUTING 1 >/dev/null 2>&1
+ systemctl stop bananapi-restore-iptables.service
+ systemctl disable bananapi-restore-iptables.service
+ rm -f /etc/iptables.ipv4.nat
+ rm -f /var/run/hostapd/* >/dev/null 2>&1
+ reload-nety
+ ;;
+
+
+ # Create WiFi access point
+ #
+ "Hotspot" )
+ if ! is_package_manager_running; then
+ systemctl daemon-reload
+ CURRENT_UUID=$(LC_ALL=C nmcli -f DEVICE,TYPE,STATE device status | grep -w " wifi " | grep -w " disconnected")
+ if [[ -n $(service hostapd status | grep -w active | grep -w running) ]]; then
+ if [[ -n $HOSTAPDBRIDGE ]]; then
+ dialog --title " Hostapd service is running " --colors --backtitle "$BACKTITLE" --help-button \
+ --help-label "Cancel" --yes-label "Stop and reboot" --no-label "Edit" --yesno \
+ "\n\Z1Stop:\Z0 stop and reboot\n\n\Z1Edit:\Z0 change basic parameters: SSID, password and channel" 9 70
+
+ else
+ dialog --title " Hostapd service is running " --colors --backtitle "$BACKTITLE" --help-button \
+ --help-label "Cancel" --yes-label "Stop" --no-label "Edit" --yesno \
+ "\n\Z1Stop:\Z0 stop providing Access Point\n\n\Z1Edit:\Z0 change basic parameters: SSID, password and channel" 9 70
+ fi
+ exitstatus=$?;
+ if [[ $exitstatus = 0 ]]; then
+ dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nDisabling hotspot. Please wait!" 5 35
+ sed -i "s/^DAEMON_CONF=.*/DAEMON_CONF=/" /etc/init.d/hostapd
+ # disable DNS
+ systemctl daemon-reload
+ systemctl disable dnsmasq.service >/dev/null 2>&1
+
+ ifdown $WIRELESS_ADAPTER 2> /dev/null
+ rm -f /etc/network/interfaces.d/bananapi.ap.*
+ rm -f /etc/dnsmasq.conf
+ iptables -t nat -D POSTROUTING 1 >/dev/null 2>&1
+ rm -f /etc/iptables.ipv4.nat
+ systemctl stop bananapi-restore-iptables.service
+ systemctl disable bananapi-restore-iptables.service
+ rm -f /var/run/hostapd/* >/dev/null 2>&1
+ sed -i '/^iptables/ d' /etc/rc.local
+ sed -i '/^service dnsmasq/ d' /etc/rc.local
+ sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ iptables -F
+ # reload services
+ reload-nety
+ [[ -n $HOSTAPDBRIDGE ]] && reboot
+ fi
+ if [[ $exitstatus = 1 ]]; then wlan_edit; reload-nety "reload"; fi
+ elif [[ -z $CURRENT_UUID ]]; then
+ dialog --title " Info " --backtitle "$BACKTITLE" --no-collapse --msgbox "\nAll wireless connections are in use." 7 40
+ else
+ # check for low quality drivers and combinations
+ check_and_warn
+
+ # remove interfaces from managed list
+ if [[ -f /etc/NetworkManager/conf.d/10-ignore-interfaces.conf ]]; then
+ sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ fi
+
+ # clear current settings
+ rm -f /etc/network/interfaces.d/bananapi.ap.nat
+ rm -f /etc/network/interfaces.d/bananapi.ap.bridge
+ service networking restart
+ service network-manager restart >/dev/null 2>&1
+ service NetworkManager restart >/dev/null 2>&1
+ { for ((i = 0 ; i <= 100 ; i+=20)); do sleep 1; echo $i; done } | dialog --title " Initializing wireless adapters " --colors --gauge "" 5 50 0
+
+ # start with basic config
+ if grep -q "^## IEEE 802.11ac" /etc/hostapd.conf; then sed '/## IEEE 802.11ac\>/,/^## IEEE 802.11ac\>/ s/.*/#&/' -i /etc/hostapd.conf; fi
+ if grep -q "^## IEEE 802.11a" /etc/hostapd.conf; then sed '/## IEEE 802.11a\>/,/^## IEEE 802.11a\>/ s/.*/#&/' -i /etc/hostapd.conf; fi
+ if grep -q "^## IEEE 802.11n" /etc/hostapd.conf; then sed '/## IEEE 802.11n/,/^## IEEE 802.11n/ s/.*/#&/' -i /etc/hostapd.conf; fi
+ sed -i "s/^channel=.*/channel=5/" /etc/hostapd.conf
+
+ service network-manager reload >/dev/null 2>&1
+ service NetworkManager reload >/dev/null 2>&1
+ # change special adapters to AP mode
+ wlan_exceptions "on"
+ # check for WLAN interfaces
+ get_wlan_interface
+ # add interface to unmanaged list
+ if [[ -f /etc/NetworkManager/conf.d/10-ignore-interfaces.conf ]]; then
+ [[ -z $(grep -w unmanaged-devices= /etc/NetworkManager/conf.d/10-ignore-interfaces.conf) ]] && sed '$ s/$/,/' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ sed '$ s/$/'"interface-name:$WIRELESS_ADAPTER"'/' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ else
+ echo "[keyfile]" > /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ echo "unmanaged-devices=interface-name:$WIRELESS_ADAPTER" >> /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ fi
+ service network-manager reload >/dev/null 2>&1
+ service NetworkManager reload >/dev/null 2>&1
+ # display dialog
+ dialog --colors --backtitle "$BACKTITLE" --title "Please wait" --infobox \
+ "\nWireless adapter: \Z1${WIRELESS_ADAPTER}\Z0\n\nProbing nl80211 hostapd driver compatibility." 7 50
+ #debconf-apt-progress -- apt-get --reinstall -o Dpkg::Options::="--force-confnew" -y -qq --no-install-recommends install hostapd
+ # change to selected interface
+ sed -i "s/^interface=.*/interface=$WIRELESS_ADAPTER/" /etc/hostapd.conf
+ # add hostapd.conf to services
+ sed -i "s/^DAEMON_CONF=.*/DAEMON_CONF=\/etc\/hostapd.conf/" /etc/init.d/hostapd
+ # check both options
+ # add allow cli access if not exists. temporally
+ if ! grep -q "ctrl_interface" /etc/hostapd.conf; then
+ echo "" >> /etc/hostapd.conf
+ echo "ctrl_interface=/var/run/hostapd" >> /etc/hostapd.conf
+ echo "ctrl_interface_group=0" >> /etc/hostapd.conf
+ fi
+ #
+ check_advanced_modes
+ #
+ if [[ -n "$hostapd_error" ]]; then
+ dialog --colors --backtitle "$BACKTITLE" --title "Please wait" --infobox \
+ "\nWireless adapter: \Z1${WIRELESS_ADAPTER}\Z0\n\nProbing Realtek hostapd driver compatibility." 7 50
+ debconf-apt-progress -- apt-get --reinstall -o Dpkg::Options::="--force-confnew" -y -qq --no-install-recommends install hostapd-realtek
+ # change to selected interface
+ sed -i "s/^interface=.*/interface=$WIRELESS_ADAPTER/" /etc/hostapd.conf
+ # add allow cli access if not exists. temporally
+ if ! grep -q "ctrl_interface" /etc/hostapd.conf; then
+ echo "ctrl_interface=/var/run/hostapd" >> /etc/hostapd.conf
+ echo "ctrl_interface_group=0" >> /etc/hostapd.conf
+ fi
+ #
+ check_advanced_modes
+ #
+ fi
+
+ if [[ -n "$hostapd_error" ]]; then
+ dialog --backtitle "$BACKTITLE" --title "Warning" \
+ --infobox "\nWireless adapter: $WIRELESS_ADAPTER\n\nNo compatible hostapd driver found." 7 39
+ sed -i "s/^DAEMON_CONF=.*/DAEMON_CONF=/" /etc/init.d/hostapd
+ # remove interfaces from managed list
+ sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
+ systemctl daemon-reload;service hostapd restart
+ fi
+
+ # let's remove bridge out for this simple configurator
+ #
+ # dialog --title " Choose Access Point mode for $WIRELESS_ADAPTER " --colors --backtitle "$BACKTITLE" --no-label "Bridge" \
+ # --yes-label "NAT" --yesno "\n\Z1NAT:\Z0 with own DHCP server, out of your primary network\n\
+ # \n\Z1Bridge:\Z0 wireless clients will use your routers DHCP server" 9 70
+ # response=$?
+ #
+ # let's remove bridge out for this simple configurator
+
+ response=0
+
+ # create interfaces file if not exits
+ [[ ! -f /etc/network/interfaces ]] && echo "source /etc/network/interfaces.d/*" > /etc/network/interfaces
+
+ # select default interfaces if there is more than one
+ select_default_interface
+
+ NETWORK_CONF="/etc/network/interfaces"
+
+ case $response in
+ # bridge
+ 1)
+ TEMP_CONF="/etc/network/interfaces.d/bananapi.ap.bridge"
+
+ sed -i 's/.bridge=.*/bridge=br0/' /etc/hostapd.conf
+ if [[ $DEFAULT_ADAPTER == "br0" ]]; then NEW_DEFAULT_ADAPTER="eth0"; else NEW_DEFAULT_ADAPTER="$DEFAULT_ADAPTER"; fi
+ echo -e "#bridged wireless for hostapd by bananapi-config\n" > $TEMP_CONF
+ echo -e "auto lo br0\niface lo inet loopback" >> $TEMP_CONF
+ echo -e "\nauto $NEW_DEFAULT_ADAPTER\nallow-hotplug $NEW_DEFAULT_ADAPTER\niface $NEW_DEFAULT_ADAPTER inet manual" >> $TEMP_CONF
+ echo -e "\nauto $WIRELESS_ADAPTER\nallow-hotplug $WIRELESS_ADAPTER\niface $WIRELESS_ADAPTER inet manual\n" >> $TEMP_CONF
+ create_if_config "$DEFAULT_ADAPTER" "br0" >> $TEMP_CONF
+ echo -e "\nbridge_ports $NEW_DEFAULT_ADAPTER $WIRELESS_ADAPTER" >> $TEMP_CONF
+
+ ;;
+ # NAT
+ 0)
+ TEMP_CONF="/etc/network/interfaces.d/bananapi.ap.nat"
+
+ # install dnsmas and iptables
+ if [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' dnsmasq 2>/dev/null) != "*ii*" ]]; then
+ debconf-apt-progress -- apt-get -qq -y --no-install-recommends install dnsmasq;
+ systemctl enable dnsmasq
+ fi
+
+ echo -e "# bananapi NAT hostapd\nallow-hotplug $WIRELESS_ADAPTER\niface $WIRELESS_ADAPTER inet static " > $TEMP_CONF
+ echo -e "\taddress 172.24.1.1\n\tnetmask 255.255.255.0\n\tnetwork 172.24.1.0\n\tbroadcast 172.24.1.255" >> $TEMP_CONF
+ # create new configuration
+ echo "interface=$WIRELESS_ADAPTER # Use interface $WIRELESS_ADAPTER" > /etc/dnsmasq.conf
+ echo "listen-address=172.24.1.1 # Explicitly specify the address to listen on" >> /etc/dnsmasq.conf
+ echo "bind-interfaces # Bind to the interface to make sure we aren't sending \
+ things elsewhere" >> /etc/dnsmasq.conf
+ echo "server=8.8.8.8 # Forward DNS requests to Google DNS" >> /etc/dnsmasq.conf
+ echo "domain-needed # Don't forward short names" >> /etc/dnsmasq.conf
+ echo "bogus-priv # Never forward addresses in the non-routed address spaces" \
+ >> /etc/dnsmasq.conf
+ echo "dhcp-range=172.24.1.50,172.24.1.150,12h # Assign IP addresses between 172.24.1.50 and 172.24.1.150 with \
+ a 12 hour lease time" >> /etc/dnsmasq.conf
+ # - Enable IPv4 forwarding
+ sed -i "/net.ipv4.ip_forward=/c\net.ipv4.ip_forward=1" /etc/sysctl.conf
+ echo 1 > /proc/sys/net/ipv4/ip_forward
+ # Clear iptables
+ iptables-save | awk '/^[*]/ { print $1 } /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; } /COMMIT/ { print $0; }' | iptables-restore
+ if [[ ${DISTRIBUTION_CODENAME} == buster ]]; then
+ echo 1 | update-alternatives --config iptables > /dev/null
+ fi
+ # - Apply iptables
+ iptables -t nat -A POSTROUTING -o $DEFAULT_ADAPTER -j MASQUERADE
+ iptables -A FORWARD -i $DEFAULT_ADAPTER -o $WIRELESS_ADAPTER -m state --state RELATED,ESTABLISHED -j ACCEPT
+ iptables -A FORWARD -i $WIRELESS_ADAPTER -o $DEFAULT_ADAPTER -j ACCEPT
+ # - Save IP tables, applied during ifup in /etc/network/interfaces.
+ iptables-save > /etc/iptables.ipv4.nat
+ sed -i 's/^bridge=.*/#&/' /etc/hostapd.conf
+ #sed -e 's/exit 0//g' -i /etc/rc.local
+ # workaround if hostapd is too slow
+ #echo "service dnsmasq start" >> /etc/rc.local
+ #echo "iptables-restore < /etc/iptables.ipv4.nat" >> /etc/rc.local
+ #echo "exit 0" >> /etc/rc.local
+ systemctl stop bananapi-restore-iptables.service
+ systemctl disable bananapi-restore-iptables.service
+ cat <<-EOF > /etc/systemd/system/bananapi-restore-iptables.service
+ [Unit]
+ Description="Restore IP tables"
+ [Timer]
+ OnBootSec=20Sec
+ [Service]
+ Type=oneshot
+ ExecStart=/sbin/iptables-restore /etc/iptables.ipv4.nat
+ [Install]
+ WantedBy=sysinit.target
+ EOF
+ systemctl enable bananapi-restore-iptables.service
+ ;;
+ 3)exit;;
+
+ 255) exit;;
+ esac
+
+ dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nEnabling hotspot. Please wait!" 5 34
+
+ #
+ # only for bridged connection we need to check and reboot. tdlr check if it can be done on the fly
+ HOSTAPDBRIDGE=$(cat /etc/hostapd.conf 2> /dev/null | grep -w "^bridge=br0")
+ if [[ -n $HOSTAPDBRIDGE ]]; then
+ dialog --title "Manually adjust network configuration if needed" --backtitle "$BACKTITLE" \
+ --ok-label "Reboot to apply new settings" --no-collapse --editbox $TEMP_CONF 30 0 2> $TEMP_CONF".tmp"
+ response=$?
+ if [[ $response = 0 ]]; then
+ mv $TEMP_CONF".tmp" $TEMP_CONF
+ #reboot
+ fi
+ else
+ ifdown $WIRELESS_ADAPTER 2> /dev/null
+ sleep 2
+ ifup $WIRELESS_ADAPTER 2> /dev/null
+ echo "nameserver 8.8.8.8" > /etc/resolvconf/resolv.conf.d/base
+ [[ "$reboot_module" == true ]] && dialog --backtitle "$BACKTITLE" --title " Warning " --msgbox "\nReboot is required for this adapter to switch to AP mode" 7 61 && reboot
+ # reload services
+ reload-nety "reload"
+ fi
+ fi
+ fi
+ ;;
+
+
+ # Manage Softether VPN
+ #
+ "VPN" )
+ VPNDIR="/usr/local/vpnclient/"
+
+ function vpn_reconfigure ()
+ {
+ if [[ -f /etc/server.vpn ]]; then
+ ${VPNDIR}vpnclient stop >/dev/null 2>&1
+ ${VPNDIR}vpnclient start >/dev/null 2>&1
+ # purge old settings
+ ${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Connection Setting Name" | cut -d "|" -f 2 | sed 's/^/"/;s/$/"/' | xargs /usr/local/vpnclient/vpncmd /client localhost /cmd accountdisconnect >/dev/null 2>&1
+ ${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Connection Setting Name" | cut -d "|" -f 2 | sed 's/^/"/;s/$/"/' | xargs /usr/local/vpnclient/vpncmd /client localhost /cmd accountdelete >/dev/null 2>&1
+ # import new
+ ${VPNDIR}vpncmd /client localhost /cmd accountimport //etc//server.vpn >/dev/null 2>&1
+ # reload to connect
+ ${VPNDIR}vpnclient stop >/dev/null 2>&1
+ ${VPNDIR}vpnclient start >/dev/null 2>&1
+ [[ $? = 0 ]] && dialog --backtitle "$BACKTITLE" --title " VPN " --msgbox "\nConfiguration was successfully imported!" 7 43
+ fi
+ }
+
+ function get_numbers {
+ EXCLUDE=$(ip neigh | grep vpn_se | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.' | head -1)
+ ADAPTER=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | grep -v vpn_se | head -1)
+ IP=$(ip route | grep $ADAPTER | grep default | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | head -1)
+ VPNSERVERIP=$(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Server" |grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | head -1)
+ SUBNET=$(ifconfig vpn_se | grep 'inet addr:' | grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}' | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')
+ GW=$(ip neigh | grep vpn_se | grep $SUBNET | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | head -1)
+ }
+
+ function raise_dev {
+ i=0;
+ while [[ -z "$TEMP" && $i<5 ]]; do
+ TEMP=$(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep Status | grep Connected)
+ sleep 1
+ i=$((i+1))
+ done
+ dhclient vpn_se
+ }
+
+ if pgrep -x "vpnclient" > /dev/null
+ then
+ ${VPNDIR}vpnclient stop >/dev/null 2>&1
+ ${VPNDIR}vpnclient start >/dev/null 2>&1
+ if [[ -z $(${VPNDIR}vpncmd /client localhost /cmd nicList | grep Enabled) ]]; then
+ ${VPNDIR}vpncmd /client localhost /cmd niccreate se >/dev/null 2>&1
+ fi
+ if [[ -z $(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Server") ]]; then
+ dialog --backtitle "$BACKTITLE" --no-label " Cancel " --yes-label " Import " --title " VPN " --yesno "\nA VPN configuration was not found.\n\nPlace valid file at /etc/server.vpn" 9 45
+ if [[ $? = 0 && -f /etc/server.vpn ]]; then
+ ${VPNDIR}vpncmd /client localhost /cmd accountimport //etc//server.vpn >/dev/null 2>&1
+ ${VPNDIR}vpnclient stop >/dev/null 2>&1
+ ${VPNDIR}vpnclient start >/dev/null 2>&1
+ [[ $? = 0 ]] && dialog --backtitle "$BACKTITLE" --title " VPN " --msgbox "\nConfiguration was successfully imported!" 7 43
+ fi
+ fi
+
+ # raise devices
+ raise_dev
+
+ if [[ -n $(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep Status | grep Connected) ]]; then
+ get_numbers
+ echo "ip route add $VPNSERVERIP via $IP dev $ADAPTER"
+ echo "ip route del default"
+ echo "ip route add default via $GW dev vpn_se"
+ read
+ dialog --title "VPN client is connected to $VPNSERVERIP" --colors --backtitle "$BACKTITLE" --help-button --help-label "Cancel" --yes-label "Stop" --no-label " Import " --yesno "\n\Z1Stop: \Z0 stop\n\n\Z1Import:\Z0 import new config from /etc/bananapi.vpn" 9 70
+ fi
+ response=$?
+ if [[ $response = 0 ]]; then
+ get_numbers
+ echo "ip route del $VPNSERVERIP"
+ echo "ip route del default"
+ echo "ip route add default via $IP dev $ADAPTER"
+ read
+ dialog --backtitle "$BACKTITLE" --nocancel --nook --infobox "\nClosing VPN connection" 5 27
+ ${VPNDIR}vpnclient stop >/dev/null 2>&1
+ fi
+ else
+ dialog --title "VPN client is disconnected" --colors --backtitle "$BACKTITLE" --help-button --help-label "Cancel" --yes-label "Connect" --no-label " Import " --yesno "\n\Z1Connect:\Z0 Connect with your VPN server \n\n\Z1Import:\Z0 import new config from /etc/bananapi.vpn" 9 70
+ response=$?
+ if [[ $response = 0 ]]; then
+ ${VPNDIR}vpnclient start >/dev/null 2>&1
+
+ # raise devices
+ raise_dev
+ get_numbers
+ echo "ip route add $VPNSERVERIP via $IP dev $ADAPTER"
+ echo "ip route del default"
+ echo "ip route add default via $GW dev vpn_se"
+ read
+
+ fi
+ [[ $response = 1 ]] && vpn_reconfigure
+ fi
+ ;;
+
+
+ # Connect to Bluetooth
+ #
+ "BT discover" )
+ dialog --backtitle "$BACKTITLE" --title " Bluetooth " --msgbox "\nVerify that your Bluetooth device is discoverable!" 7 54
+ connect_bt_interface
+ ;;
+
+
+ # Edit network settings
+ #
+ "Advanced" )
+ dialog --backtitle "$BACKTITLE" --title " Edit ifupdown network configuration /etc/network/interfaces" --no-collapse \
+ --ok-label "Save" --editbox /etc/network/interfaces 30 0 2> /etc/network/interfaces.out
+ [[ $? = 0 ]] && mv /etc/network/interfaces.out /etc/network/interfaces && reload-nety "reload"
+ ;;
+
+ # Remove automatic wifi conections
+ #
+ "Forget" )
+ LC_ALL=C nmcli --fields UUID,TIMESTAMP-REAL,TYPE con show | grep wifi | awk '{print $1}' | while read line; \
+ do nmcli con delete uuid $line; done > /dev/null
+ ;;
+
+
+
+
+ #-------------------------------------------------------------------------------------------------------------------------------------#
+ #-------------------------------------------------------------------------------------------------------------------------------------#
+ #-------------------------------------------------------------------------------------------------------------------------------------#
+
+
+
+
+ # Change timezone
+ #
+ "Timezone" )
+ dpkg-reconfigure tzdata
+ ;;
+
+
+ # Change locales
+ #
+ "Locales" )
+ dpkg-reconfigure locales
+ source /etc/default/locale
+ sed -i "s/^LANGUAGE=.*/LANGUAGE=$LANG/" /etc/default/locale
+ export LANGUAGE=$LANG
+ ;;
+
+ # Change keyboard
+ #
+ "Keyboard" )
+ dpkg-reconfigure keyboard-configuration
+ setupcon
+ ;;
+
+ # Change Hostname
+ #
+ "Hostname" )
+ hostname_current=$(cat /etc/hostname)
+ hostname_new=$(\
+ dialog --no-cancel --title " Change hostname " --backtitle "$BACKTITLE" --inputbox "\nType new hostname\n " 10 50 $hostname_current \
+ 3>&1 1>&2 2>&3 3>&- \
+ )
+ if [[ $? = 0 && -n $hostname_new ]]; then
+ sed -i "s/$hostname_current/$hostname_new/g" /etc/hosts
+ sed -i "s/$hostname_current/$hostname_new/g" /etc/hostname
+ hostname $hostname_new
+ systemctl restart systemd-logind.service
+ dialog --title " Info " --backtitle "$BACKTITLE" --no-collapse --msgbox "\nYou need to logout to make the changes effective." 7 53
+ fi
+ ;;
+
+ # Bash
+ #
+ "BASH" )
+ # change shell for root
+ chsh -s /bin/bash
+ add_choose_user
+ if [ -n "$CHOSEN_USER" ]; then
+ chsh -s /bin/bash $CHOSEN_USER
+ fi
+ # cleanup
+ rm -rf /etc/oh-my-zsh /etc/skel/.zshrc /etc/skel/.oh-my-zsh
+ rm -rf /root/{.zshrc,.oh-my-zsh}
+ # and for selected normal user
+ add_choose_user
+ if [ -n "$CHOSEN_USER" ]; then
+ rm -rf /home/$CHOSEN_USER/{.zshrc,.oh-my-zsh}
+ fi
+ # change shell for future users
+ sed -i "s/^SHELL=.*/SHELL=\/bin\/bash/" /etc/default/useradd
+ # remove crontab
+ crontab -l | grep -v oh-my | crontab -
+ if [[ -z $scripted ]]; then
+ dialog --backtitle "$BACKTITLE" --title "Info" --colors --msgbox "\nYour default shell was switched to: \Z1BASH\Z0\n\nPlease logout & login from this session!" 9 47
+ fi
+ ;;
+
+
+ # ZSH
+ #
+ "ZSH" )
+ if ! is_package_manager_running; then
+ if ! check_if_installed zsh ; then
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get install -y zsh tmux git
+ fi
+ rm -rf /etc/oh-my-zsh
+ git clone --quiet https://github.com/robbyrussell/oh-my-zsh.git /etc/oh-my-zsh
+ cp /etc/oh-my-zsh/templates/zshrc.zsh-template /etc/skel/.zshrc
+ mkdir -p /etc/skel/.oh-my-zsh/cache
+ # change shell for future users
+ sed -i "s/^SHELL=.*/SHELL=\/usr\/bin\/zsh/" /etc/default/useradd
+ # we have common settings
+ sed -i "s/^export ZSH=.*/export ZSH=\/etc\/oh-my-zsh/" /etc/skel/.zshrc
+ # user cache
+ sed -i "/^export ZSH=.*/a export ZSH_CACHE_DIR=~\/.oh-my-zsh\/cache" /etc/skel/.zshrc
+ # define theme
+ sed -i 's/^ZSH_THEME=.*/ZSH_THEME="risto"/' /etc/skel/.zshrc
+ # disable prompt while update
+ sed -i 's/# DISABLE_UPDATE_PROMPT="true"/DISABLE_UPDATE_PROMPT="true"/g' /etc/skel/.zshrc
+ # define default plugins
+ sed -i 's/^plugins=.*/plugins=(git git-extras debian tmux screen history extract colorize web-search docker)/' /etc/skel/.zshrc
+ # change shell for root
+ chsh -s $(grep /zsh$ /etc/shells | tail -1)
+ # copy cache directory
+ cp -R --attributes-only /etc/skel/.oh-my-zsh /root/.oh-my-zsh
+ cp /etc/skel/.zshrc /root/.zshrc
+ # and for selected normal user
+ add_choose_user
+ if [ -n "$CHOSEN_USER" ]; then
+ chsh -s $(grep /zsh$ /etc/shells | tail -1) $CHOSEN_USER
+ # copy cache directory
+ cp -R --attributes-only /etc/skel/.oh-my-zsh /home/$CHOSEN_USER/.oh-my-zsh
+ cp /etc/skel/.zshrc /home/$CHOSEN_USER/.zshrc
+ chown -R ${CHOSEN_USER}:${CHOSEN_USER} /home/${CHOSEN_USER}/{.zshrc,.oh-my-zsh}
+ fi
+ # add a cronjob to update oh-my-zsh once per month
+ (crontab -l 2>/dev/null; echo "0 0 1 * * cd /etc/oh-my-zsh ; git pull origin master >/dev/null 2>/dev/null") | crontab -
+ if [[ -z $scripted ]]; then
+ dialog --backtitle "$BACKTITLE" --title "Info" --colors --msgbox "\nYour default shell was switched to: \Z1ZSH\Z0\n\nPlease logout & login from this session!" 9 47
+ fi
+ fi
+ ;;
+
+
+ # Firmware update
+ #
+ "Firmware" )
+ if ! is_package_manager_running; then
+ clear
+ exec 3>&1
+ monitor=$(dialog --print-maxsize 2>&1 1>&3)
+ exec 3>&-
+ mon_x=$(echo $monitor | awk '{print $2}' | sed 's/,//');mon_x=$(( $mon_x / 2 ))
+ mon_y=$(echo $monitor | awk '{print $3}' | sed 's/,//');
+ if [[ -z $scripted ]]; then
+ dialog --title " Update " --backtitle "$BACKTITLE" --no-label "No" --yesno "\nDo you want to update board firmware?" 7 41
+ fi
+ if [[ $? -eq 0 ]]; then
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y upgrade
+ [[ -z $scripted ]] && \
+ dialog --title " Firmware update " --colors --no-label "No" --backtitle "$BACKTITLE" --yesno \
+ "\nFirmware has been updated. Reboot? " 7 39
+ if [[ $? -eq 0 ]]; then reboot; fi
+ fi
+ fi
+ ;;
+
+
+ # Install to SATA, eMMC, NAND or USB
+ #
+ "Install" )
+ nand-sata-install
+ ;;
+
+
+ # Freeze and unfreeze kernel and board support packages
+ #
+ "Freeze" | "Defreeze" )
+ if ! is_package_manager_running; then
+ if [[ -z $scripted ]]; then dialog --title " Updating " --backtitle "$BACKTITLE" --yes-label "$1" --no-label "Cancel" --yesno \
+ "\nDo you want to ${1,,} Orange Pi firmware updates?" 7 54
+ fi
+ if [[ $? -eq 0 ]]; then
+
+ unset PACKAGE_LIST
+
+ # basic packages
+
+ check_if_installed linux-u-boot-${BOARD}-${BRANCH} && PACKAGE_LIST+=" linux-u-boot-${BOARD}-${BRANCH}"
+ check_if_installed linux-image-${BRANCH}-${LINUXFAMILY} && PACKAGE_LIST+=" linux-image-${BRANCH}-${LINUXFAMILY}"
+ check_if_installed linux-dtb-${BRANCH}-${LINUXFAMILY} && PACKAGE_LIST+=" linux-dtb-${BRANCH}-${LINUXFAMILY}"
+ check_if_installed linux-headers-${BRANCH}-${LINUXFAMILY} && PACKAGE_LIST+=" linux-headers-${BRANCH}-${LINUXFAMILY}"
+
+ # new BSP
+ check_if_installed bananapi-${LINUXFAMILY} && PACKAGE_LIST+=" bananapi-${LINUXFAMILY}"
+ check_if_installed bananapi-${BOARD} && PACKAGE_LIST+=" bananapi-${BOARD}"
+ check_if_installed bananapi-${DISTROID} && PACKAGE_LIST+=" bananapi-${DISTROID}"
+ check_if_installed bananapi-${DISTROID}-desktop-xfce && PACKAGE_LIST+=" bananapi-${DISTROID}-desktop-xfce"
+ check_if_installed bananapi-firmware && PACKAGE_LIST+=" bananapi-firmware"
+ check_if_installed bananapi-firmware-full && PACKAGE_LIST+=" bananapi-firmware-full"
+
+ local words=( $PACKAGE_LIST )
+ local command="unhold"
+ IFS=" "
+ [[ $1 == "Freeze" ]] && local command="hold"
+ for word in $PACKAGE_LIST; do apt-mark $command $word; done | dialog --backtitle "$BACKTITLE" --title "Packages ${1,,}" --progressbox $((${#words[@]}+2)) 64
+ fi
+ fi
+ ;;
+
+
+ # Switch to other kernel versions
+ "Other")
+ if ! is_package_manager_running; then
+ other_kernel_version
+ fi
+ ;;
+
+
+
+ # Enable or disable desktop
+ #
+ "Desktop" )
+ if [[ -n $DISPLAY_MANAGER ]]; then
+ dialog --title " Desktop is enabled and running " --backtitle "$BACKTITLE" \
+ --yes-label "Stop" --no-label "Cancel" --yesno "\nDo you want to stop and disable this service?" 7 50
+ exitstatus=$?;
+ if [[ $exitstatus = 0 ]]; then
+ function stop_display()
+ {
+ bash -c "service lightdm stop >/dev/null 2>&1
+ systemctl disable lightdm.service >/dev/null 2>&1
+ service nodm stop >/dev/null 2>&1
+ systemctl disable nodm.service >/dev/null 2>&1"
+ }
+ if xhost >& /dev/null ; then
+ stop_display &
+ else
+ stop_display
+ fi
+ fi
+ else
+ if ! is_package_manager_running; then
+ # remove nodm and install lightdm = backward compatibility
+ [[ -n $(dpkg -l | grep nodm) ]] && debconf-apt-progress -- apt-get -y purge nodm
+ [[ -z $(dpkg -l | grep lightdm) ]] && debconf-apt-progress -- apt-get -o Dpkg::Options::="--force-confold" -y --no-install-recommends install lightdm-gtk-greeter lightdm
+ if [[ -n $DESKTOP_INSTALLED ]]; then
+ dialog --title " Display manager " --backtitle "$BACKTITLE" --yesno "\nDo you want to enable autologin?" 7 36
+ exitstatus=$?;
+ if [[ $exitstatus = 0 ]]; then
+ add_choose_user
+ if [ -n "$CHOSEN_USER" ]; then
+ mkdir -p /etc/lightdm/lightdm.conf.d
+ echo "[Seat:*]" > /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ echo "autologin-user=$CHOSEN_USER" >> /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ echo "autologin-user-timeout=0" >> /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ echo "user-session=xfce" >> /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf
+ ln -s /lib/systemd/system/lightdm.service /etc/systemd/system/display-manager.service >/dev/null 2>&1
+ service lightdm start >/dev/null 2>&1
+ fi
+ else
+ rm /etc/lightdm/lightdm.conf.d/22-bananapi-autologin.conf >/dev/null 2>&1
+ ln -s /lib/systemd/system/lightdm.service /etc/systemd/system/display-manager.service >/dev/null 2>&1
+ service lightdm start >/dev/null 2>&1
+ fi
+ # kill this bash script after desktop is up and if executed on console
+ [[ $(tty | sed -e "s:/dev/::") == tty* ]] && kill -9 $$
+ fi
+ fi
+ fi
+ ;;
+
+ "Default" )
+ configure_desktop "--install-recommends"
+ ;;
+
+ "RDP" )
+ if [[ -n $(service xrdp status | grep -w active) ]]; then
+ systemctl stop xrdp.service >/dev/null 2>&1
+ systemctl disable xrdp.service >/dev/null 2>&1
+ else
+ if ! is_package_manager_running; then
+ debconf-apt-progress -- apt-get -y install xrdp vnc4server xorgxrdp
+ systemctl enable xrdp.service >/dev/null 2>&1
+ systemctl start xrdp.service >/dev/null 2>&1
+ dialog --title "Info" --backtitle "$BACKTITLE" --nocancel --no-collapse --pause \
+ "\nRemote graphical login to $BOARD_NAME using Microsoft Remote Desktop Protocol (RDP) is enabled." 11 57 3
+
+ fi
+ fi
+ ;;
+
+ "Thunderbird" )
+ if ! check_if_installed thunderbird then ; then
+ debconf-apt-progress -- apt-get -y install thunderbird
+ else
+ debconf-apt-progress -- apt-get -y purge thunderbird
+ fi
+ ;;
+
+ "Gimp" )
+ if ! check_if_installed gimp then ; then
+ debconf-apt-progress -- apt-get -y install gimp
+ else
+ debconf-apt-progress -- apt-get -y purge gimp
+ fi
+ ;;
+
+ "Libre" )
+ debconf-apt-progress -- apt-get -y purge libreoffice*
+ ;;
+
+ "Writer" )
+ pkg_install="libreoffice-writer libreoffice-style-tango"
+ if [[ "$DISTROID" == "xenial" ]]; then pkg_install+=" libreoffice-gtk"; else pkg_install+=" libreoffice-gtk2"; fi
+ debconf-apt-progress -- apt-get -y install $pkg_install
+ ;;
+
+ "Suite" )
+ pkg_install="libreoffice libreoffice-style-tango"
+ if [[ "$DISTROID" == "xenial" ]]; then pkg_install+=" libreoffice-gtk"; else pkg_install+=" libreoffice-gtk2"; fi
+ debconf-apt-progress -- apt-get -y install $pkg_install
+ ;;
+
+
+ # Stop low-level messages on console
+ #
+ "Lowlevel" )
+ dialog --title " Kernel messages " --backtitle "$BACKTITLE" --help-button \
+ --help-label "Yes & reboot" --yes-label "Yes" --no-label "Cancel" --yesno "\nStop low-level messages on console?" 7 64
+ exitstatus=$?;
+ [[ $exitstatus = 0 ]] && sed -i 's/^#kernel.printk\(.*\)/kernel.printk\1/' /etc/sysctl.conf
+ [[ $exitstatus = 2 ]] && sed -i 's/^#kernel.printk\(.*\)/kernel.printk\1/' /etc/sysctl.conf && reboot
+ ;;
+
+ # CPU speed and governor
+ #
+ "CPU" )
+ POLICY="policy0"
+ [[ $(grep -c '^processor' /proc/cpuinfo) -gt 4 ]] && POLICY="policy4"
+ [[ ! -d /sys/devices/system/cpu/cpufreq/policy4 ]] && POLICY="policy0"
+ generic_select "$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_available_frequencies)" "Select minimum CPU speed"
+ MIN_SPEED=$PARAMETER
+ generic_select "$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_available_frequencies)" "Select maximum CPU speed" "$PARAMETER"
+ MAX_SPEED=$PARAMETER
+ generic_select "$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_available_governors)" "Select CPU governor"
+ GOVERNOR=$PARAMETER
+ if [[ -n $MIN_SPEED && -n $MAX_SPEED && -n $GOVERNOR ]]; then
+ dialog --colors --title " Apply and save changes " --backtitle "$BACKTITLE" --yes-label "OK" --no-label "Cancel" --yesno \
+ "\nCPU frequency will be within \Z1$(($MIN_SPEED / 1000))\Z0 and \Z1$(($MAX_SPEED / 1000)) MHz\Z0. The governor \Z1$GOVERNOR\Z0 will decide which speed to use within this range." 9 58
+ if [[ $? -eq 0 ]]; then
+ sed -i "s/MIN_SPEED=.*/MIN_SPEED=$MIN_SPEED/" /etc/default/cpufrequtils
+ sed -i "s/MAX_SPEED=.*/MAX_SPEED=$MAX_SPEED/" /etc/default/cpufrequtils
+ sed -i "s/GOVERNOR=.*/GOVERNOR=$GOVERNOR/" /etc/default/cpufrequtils
+ systemctl restart cpufrequtils
+ sync
+ fi
+ fi
+ ;;
+
+ "Avahi")
+ if ! is_package_manager_running; then
+ if check_if_installed avahi-daemon ; then
+ service avahi-daemon stop
+ debconf-apt-progress -- apt-get -y purge avahi-daemon
+ else
+ debconf-apt-progress -- apt-get -y install avahi-daemon
+ [[ -f /usr/share/doc/avahi-daemon/examples/sftp-ssh.service ]] && cp /usr/share/doc/avahi-daemon/examples/sftp-ssh.service /etc/avahi/services/
+ [[ -f /usr/share/doc/avahi-daemon/examples/ssh.service ]] && cp /usr/share/doc/avahi-daemon/examples/ssh.service /etc/avahi/services/
+ service avahi-daemon restart
+ fi
+ fi
+ ;;
+
+
+ # Edit boot environment
+ #
+ "Bootenv" )
+ dialog --title " Edit u-boot environment " --ok-label "Save" \
+ --no-collapse --editbox /boot/bananapiEnv.txt 30 0 2> /boot/bananapiEnv.txt.out
+ [[ $? = 0 ]] && mv /boot/bananapiEnv.txt.out /boot/bananapiEnv.txt
+ sync
+ ;;
+
+ # Edit boot script
+ #
+ "Bootscript" )
+ if [[ -f /boot/boot.ini ]]; then
+ dialog --title " Edit boot.ini script " --ok-label "Save" \
+ --no-collapse --editbox /boot/boot.ini 30 0 2> /boot/boot.ini.out
+ [[ $? = 0 ]] && mv /boot/boot.ini.out /boot/boot.ini
+ fi
+ ;;
+
+
+ # Toggle overlay items
+ #
+ "Hardware" )
+ # check if user agree to enter this area
+ CHANGES="false"
+ while true; do
+ overlay_prefix=$(cat /boot/bananapiEnv.txt | grep overlay_prefix | sed 's/overlay_prefix=//g')
+ TARGET_BRANCH=$BRANCH
+ exceptions "$BRANCH"
+ MOTD=()
+ LINES=()
+ LIST_CONST=-3
+ j=0
+ DIALOG_CANCEL=1
+ DIALOG_ESC=255
+ while read line
+ do
+ STATUS=$([[ -n $(cat /boot/bananapiEnv.txt | grep overlays | grep -w ${line}) ]] && echo "on")
+ DESC=$(description "$line")
+ MOTD+=( "$line" "$DESC" "$STATUS")
+ LINES[ $j ]=$line
+ (( j++ ))
+ done < <(ls -1 ${OVERLAYDIR}/${overlay_prefix}*.dtbo | sed 's/^.*\('${overlay_prefix}'.*\)/\1/g' | sed 's/'${overlay_prefix}'-//g' | sed 's/.dtbo//g' )
+
+ exec 3>&1
+ selection=$(dialog --backtitle "$BACKTITLE" --colors --title "Toggle hardware configuration" --clear --cancel-label \
+ "Back" --ok-label "Save" --checklist "\nUse \Z1\Z0 to toggle functions and save them. Exit when you are done.\n " \
+ 0 0 0 "${MOTD[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+
+ case $exit_status in
+ $DIALOG_ESC)
+ break
+ ;;
+ 0)
+ CHANGES="true"
+ newoverlays="$(echo "$selection" | sed "s|[^ ]* *|&|g")"
+ sed -i "s/^overlays=.*/overlays=$newoverlays/" /boot/bananapiEnv.txt
+ if ! grep -q "overlays" /boot/bananapiEnv.txt; then echo "overlays=$newoverlays" >> /boot/bananapiEnv.txt; fi
+ if [[ -z $newoverlays ]]; then sed -i "/^overlays/d" /boot/bananapiEnv.txt; fi
+ sync
+ ;;
+ 1)
+ if [[ "$CHANGES" == "true" ]]; then
+ dialog --title " Applying changes " --backtitle "$BACKTITLE" --yes-label "Reboot" \
+ --no-label "Cancel" --yesno "\nReboot to enable new features?" 7 34
+ if [[ $? = 0 ]]; then reboot; else break; fi
+ else
+ break
+ fi
+ ;;
+ esac
+ done
+
+ ;;
+
+ # Change to other mirrors
+ #
+ "Mirror" )
+
+ IFS=$'\r\n'
+ GLOBIGNORE='*'
+ LIST_CONST=3
+ BEFORE="$(cat /etc/apt/sources.list.d/bananapi.list | sed 's/http/\nhttp/g' | grep ^http | sed 's/\(^http[^ <]*\)\(.*\)/\1/g' | sed 's/https\?:\/\///')"
+ BEFORE_DESC=$(description "${BEFORE}")
+ PREFIX="$(echo $BEFORE | cut -f1 -d".")"
+ AVAL_MIRROR=()
+ if [[ $PREFIX == beta ]]; then
+ AVAL_MIRROR=("beta.armbian.com" "mirrors.netix.net/armbian/apt/")
+ else
+ AVAL_MIRROR+=("apt.armbian.com" "mirrors.tuna.tsinghua.edu.cn/bananapi/" "mirrors.netix.net/bananapi/apt/" "mirrors.dotsrc.org/bananapi-apt/")
+ fi
+ local LIST=()
+ for i in "${AVAL_MIRROR[@]}"
+ do
+ DESC=$(description "${i[0]}")
+ [[ "${i[0]}" != "$BEFORE" ]] && LIST+=( "${i[0]//[[:blank:]]/}" "$DESC" )
+ done
+ LIST_LENGTH=$(($LIST_CONST+${#LIST[@]}/2));
+ if [ "$LIST_LENGTH" -le 3 ]; then
+ TARGET_MIRROR=${AVAL_MIRROR[0]}
+ dialog --backtitle "$BACKTITLE" --title "Please wait" --colors --msgbox "\nThere are no mirrors available!" 7 35
+ else
+ exec 3>&1
+ TARGET_MIRROR=$(dialog --cancel-label "Cancel" --backtitle "$BACKTITLE" --no-collapse \
+ --title "Change repository location" --colors --clear --menu "\nfrom \Z1$BEFORE_DESC\Z0 to:\n " $((6+${LIST_LENGTH})) 60 15 "${LIST[@]}" 2>&1 1>&3)
+ exitstatus=$?;
+ exec 3>&-
+ fi
+
+ if [[ $exitstatus == 0 ]]; then
+ sed -i "s~$BEFORE~$TARGET_MIRROR~" /etc/apt/sources.list.d/bananapi.list
+ dialog --backtitle "$BACKTITLE" --title "Info" --colors --msgbox "\nOrange Pi package repository was switched to:\n\n\Z1$TARGET_MIRROR\Z0" 9 47
+ fi
+ ;;
+
+ # Toggle welcome screen items
+ #
+ "Welcome" )
+ while true; do
+ HOME="/etc/update-motd.d/"
+ MOTD=()
+ LINES=()
+ LIST_CONST=9
+ j=0
+ DIALOG_CANCEL=1
+ DIALOG_ESC=255
+
+ while read line
+ do
+ STATUS=$([[ -x ${HOME}${line} ]] && echo "on")
+ DESC=$(description "$line")
+ MOTD+=( "$line" "$DESC" "$STATUS")
+ LINES[ $j ]=$line
+ (( j++ ))
+ done < <(ls -1 $HOME)
+
+ LISTLENGTH="$(($LIST_CONST+${#MOTD[@]}/3))"
+ exec 3>&1
+ selection=$(dialog --backtitle "$BACKTITLE" --title "Toggle motd executing scripts" --clear --cancel-label \
+ "Back" --ok-label "Save" --checklist "\nChoose what you want to enable or disable:\n " \
+ $LISTLENGTH 80 15 "${MOTD[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ case $exit_status in
+ $DIALOG_CANCEL | $DIALOG_ESC)
+ break
+ ;;
+ 0)
+ chmod -x ${HOME}*
+ chmod +x $(echo "$selection" | sed "s|[^ ]* *|${HOME}&|g")
+ ;;
+ esac
+ done
+ ;;
+
+
+ # Toggle sshd options
+ #
+ "SSH" )
+ if ! is_package_manager_running; then
+ while true; do
+ if ! check_if_installed libpam-google-authenticator ; then
+ debconf-apt-progress -- apt-get -y install libpam-google-authenticator
+ fi
+ if ! check_if_installed qrencode ; then
+ debconf-apt-progress -- apt-get -y install qrencode
+ fi
+ DIALOG_CANCEL=2
+ DIALOG_ESC=255
+ LIST_CONST=9
+ WINDOW_SIZE=21
+
+ # variables cleanup
+ PermitRootLogin="";
+ PubkeyAuthentication="";
+ PasswordAuthentication="";
+ PhoneAuthentication=""
+ MergeParameter="";
+ ExtraDesc="";
+
+ Buttons="--no-cancel --ok-label "Save" --help-button --help-label Cancel"
+
+ # read values
+ [[ $(grep "^PermitRootLogin" /etc/ssh/sshd_config | awk '{print $2}') == "yes" ]] && PermitRootLogin="on"
+ [[ $(grep "^@include common-auth" /etc/pam.d/sshd | awk '{print $2}') == "common-auth" ]] && PasswordAuthentication="on"
+ [[ $(grep "^PubkeyAuthentication" /etc/ssh/sshd_config | awk '{print $2}') == "yes" ]] && PubkeyAuthentication="on"
+ [[ -n $(grep "pam_google_authenticator.so" /etc/pam.d/sshd) ]] && PhoneAuthentication="on"
+
+ # create menu
+ MOTD=( "PermitRootLogin" "Allow root login" "$PermitRootLogin" )
+ MOTD+=( "PasswordAuthentication" "Password login" "$PasswordAuthentication" )
+ MOTD+=( "PubkeyAuthentication" "SSH key login" "$PubkeyAuthentication" )
+ MOTD+=( "PhoneAuthentication" "Google two-step authentication with one-time passcode" "$PhoneAuthentication" )
+
+ Buttons="--no-cancel --ok-label "Save" --help-button --help-label Cancel"
+ if [[ $PhoneAuthentication == "on" ]]; then
+ Buttons="--cancel-label Generate-token --ok-label "Save" --help-button --help-label Cancel"
+ ExtraDesc="\n\Z1Note:\Z0 Two-step verification token is identical for all users on the system.\n \n"
+ LIST_CONST=11
+ if [[ -f ~/.google_authenticator ]]; then
+ Buttons="--cancel-label New-token --ok-label "Save" --help-button --help-label Cancel --extra-button --extra-label Show-token"
+ fi
+ fi
+
+ LISTLENGTH="$((${#MOTD[@]}/3))"
+ HEIGHT="$((LISTLENGTH + $LIST_CONST))"
+
+ exec 3>&1
+ selection=$(dialog --colors $Buttons --backtitle "$BACKTITLE" --title " Toggle sshd options " --clear --checklist \
+ "\nChoose what you want to enable or disable:\n $ExtraDesc" $HEIGHT 0 $LISTLENGTH "${MOTD[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+
+ case $exit_status in
+ $DIALOG_CANCEL | $DIALOG_ESC)
+ break
+ ;;
+ 0)
+ # read values, adjust config and restart service
+ my_array=($selection)
+ for((n=0;n<${#MOTD[@]};n++)); do
+ if (( $(($n % 3 )) == 0 )); then
+
+ # generic options if any
+ if [[ " ${my_array[*]} " == *" ${MOTD[$n]} "* ]]; then
+ sed -i "s/^#\?${MOTD[$n]}.*/${MOTD[$n]} yes/" /etc/ssh/sshd_config
+ else
+ sed -i "s/^#\?${MOTD[$n]}.*/${MOTD[$n]} no/" /etc/ssh/sshd_config
+ fi
+
+ if [[ $n -eq 0 ]]; then
+
+ # phone
+ if [[ " ${my_array[*]} " == *" PhoneAuthentication "* ]]; then
+ MergeParameter="keyboard-interactive"
+ sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/" /etc/ssh/sshd_config
+ sed -i -n '/password updating/{p;:a;N;/@include common-password/!ba;s/.*\n/auth required pam_google_authenticator.so nullok\n/};p' /etc/pam.d/sshd
+ else
+ MergeParameter=""
+ sed -i '/^auth required pam_google_authenticator.so nullok/ d' /etc/pam.d/sshd
+ sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/" /etc/ssh/sshd_config
+ fi
+
+ # password
+ if [[ " ${my_array[*]} " == *" PasswordAuthentication "* ]]; then
+ MergeParameter="password keyboard-interactive"
+ sed -i "s/^#\?PasswordAuthentication.*/PasswordAuthentication yes/" /etc/ssh/sshd_config
+ sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/" /etc/ssh/sshd_config
+ sed -i "s/^\#@include common-auth/\@include common-auth/" /etc/pam.d/sshd
+ else
+ sed -i "s/^#\?PasswordAuthentication.*/PasswordAuthentication no/" /etc/ssh/sshd_config
+ #sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/" /etc/ssh/sshd_config
+ sed -i "s/^\@include common-auth/\#@include common-auth/" /etc/pam.d/sshd
+ fi
+
+ # pubkey
+ if [[ " ${my_array[*]} " == *" PubkeyAuthentication "* ]]; then
+ MergeParameter="publickey keyboard-interactive "
+ sed -i "s/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/" /etc/ssh/sshd_config
+ else
+ sed -i "s/^#\?PubkeyAuthentication.*/PubkeyAuthentication no/" /etc/ssh/sshd_config
+ fi
+
+
+ if [[ " ${my_array[*]} " == *" PubkeyAuthentication "* && " ${my_array[*]} " == *" PhoneAuthentication "* ]]; then
+ MergeParameter="publickey,password publickey,keyboard-interactive"
+ sed -i "s/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/" /etc/ssh/sshd_config
+ fi
+
+
+ fi
+ fi
+ done
+
+ if [[ -z $MergeParameter ]]; then
+ sed -i '/^AuthenticationMethods.*/ d' /etc/ssh/sshd_config
+ else
+ sed -i '/^AuthenticationMethods.*/ d' /etc/ssh/sshd_config
+ sed -i -n '/and ChallengeResponseAuthentication to/{p;:a;N;/UsePAM yes/!ba;s/.*\n/AuthenticationMethods '"$MergeParameter"'\n/};p' /etc/ssh/sshd_config
+ fi
+
+ # reload sshd
+ systemctl restart sshd.service
+ ;;
+ 3)
+ display_qr_code
+ ;;
+ 1)
+ dialog --colors --title " \Z1Warning\Z0 " --backtitle "$BACKTITLE" --yes-label "Generate" --no-label "No" --yesno "\nWhen you generate new token you have to scan it with your mobile device again.\n\nUnderstand?" 10 48
+ if [[ $? = 0 ]]; then
+ google-authenticator -t -d -f -r 3 -R 30 -W -q
+ google_token_allusers
+ display_qr_code
+ fi
+ ;;
+ esac
+ done
+ fi
+ ;;
+
+
+
+ # Switch to daily builds
+ #
+ "Nightly" )
+
+ if ! is_package_manager_running; then
+ [[ -z $scripted ]] &&
+ dialog --colors --title " \Z1Warning\Z0 " --backtitle "$BACKTITLE" --yes-label "Yes" \
+ --no-label "No" --yesno \
+ "\nYou are switching to an untested auto-build repository which might break your system.\n\nContinue?" 10 48
+
+ if [[ $? = 0 || -n $scripted ]]; then
+ sed -i 's/^deb http:\/\/[^ ]*/deb http:\/\/beta.armbian.com/' /etc/apt/sources.list.d/armbian.list
+ reload_bsp $branch
+ fi
+ fi
+ ;;
+
+
+ # Switch to stable builds
+ #
+ "Stable" )
+
+ if ! is_package_manager_running; then
+ [[ -z $scripted ]] &&
+ dialog --colors --title " \Z1Warning\Z0 " --backtitle "$BACKTITLE" --yes-label "Yes" \
+ --no-label "No" --yesno \
+ "\nYou are switching to a stable repository where you will receive future updates.\n\nContinue?" 9 44
+
+ if [[ $? = 0 || -n $scripted ]]; then
+ sed -i 's/^deb http:\/\/beta/deb http:\/\/apt/' /etc/apt/sources.list.d/armbian.list
+ reload_bsp $branch
+ fi
+ fi
+
+ ;;
+
+ # Switch to alternative configurations
+ #
+ "DTB" )
+ if ! is_package_manager_running; then
+ aval_dtbs
+ if [[ $exitstatus = 0 ]]; then
+ BOX_LENGTH=$((${#TARGET_BOARD}+28));
+ dialog --title "Switching board config" --backtitle "$BACKTITLE" --yes-label "Reboot" --no-label "Cancel" --yesno "\nReboot to $TARGET_BOARD settings?" 7 $BOX_LENGTH
+ if [[ $? = 0 ]]; then
+ sed -i "s/^fdt_file=.*/fdt_file=$TARGET_BOARD/" /boot/bananapiEnv.txt 2> /dev/null && grep -q "fdt_file=$TARGET_BOARD" /boot/bananapiEnv.txt 2> /dev/null || echo "fdt_file=$TARGET_BOARD" >> /boot/bananapiEnv.txt
+ [[ "$LINUXFAMILY" = odroidxu4 ]] && sed -i "s/^fdt_file/board_name/" /boot/bananapiEnv.txt && sed -i "s/^BOARD_NAME.*/BOARD_NAME=\"Odroid ${TARGET_BOARD^^}\"/" /etc/bananapi-release
+ reboot;
+ fi
+ fi
+ fi
+ ;;
+
+
+ # Toggle virtual read-only root filesystem
+ #
+ "Overlayroot" )
+ if ! is_package_manager_running; then
+ if [[ -n $(mount | grep -w overlay | grep -v chromium) ]]; then
+ dialog --title " Root overlay " --backtitle "$BACKTITLE" --yes-label "Disable" \
+ --no-label "Cancel" \
+ --yesno "\nYour system is already virtual read-only.\n\nDo you want to disable this feature and reboot?" 9 60
+ [[ $? = 0 ]] && overlayroot-chroot sed -i "s/^overlayroot=.*/overlayroot=\"\"/" /etc/overlayroot.conf && \
+ overlayroot-chroot rm /etc/update-motd.d/97-overlayroot && reboot
+ else
+ debconf-apt-progress -- apt-get -o Dpkg::Options::="--force-confnew" -y --no-install-recommends install overlayroot
+ echo '#!/bin/bash' > /etc/update-motd.d/97-overlayroot
+ echo 'if [ -n "$(mount | grep -w tmpfs-root)" ]; then \
+ echo -e "[\e[0m \e[1mremember: your system is in virtual read only mode\e[0m ]\n";fi' >> /etc/update-motd.d/97-overlayroot
+ chmod +x /etc/update-motd.d/97-overlayroot
+ dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
+ --no-label "Cancel" --yesno "\nEnable virtual read-only root and reboot." 7 45
+ [[ ! -f /etc/overlayroot.conf ]] && cp /etc/overlayroot.conf.dpkg-new /etc/overlayroot.conf
+ [[ $? = 0 ]] && sed -i "s/^overlayroot=.*/overlayroot=\"tmpfs\"/" /etc/overlayroot.conf && reboot
+ fi
+ fi
+ ;;
+
+
+ esac
+
+
+[[ -n $scripted ]] && exit
+}
diff --git a/external/cache/sources/bananapi-config/debian-config-submenu b/external/cache/sources/bananapi-config/debian-config-submenu
new file mode 100644
index 0000000..c737535
--- /dev/null
+++ b/external/cache/sources/bananapi-config/debian-config-submenu
@@ -0,0 +1,438 @@
+#!/bin/bash
+#
+# Copyright (c) 2018 Igor Pecovnik, igor.pecovnik@gma**.com
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+# Functions:
+# submenu_settings
+# submenu_networking
+# submenu_personal
+# submenu_software
+
+
+
+#
+# system settings
+#
+function submenu_settings ()
+{
+unset main
+while true; do
+
+ LIST=()
+ DIALOG_CANCEL=1
+ DIALOG_ESC=255
+
+ # detect desktop
+ check_desktop
+
+ # check update status of BSP packages
+ local mark=$(apt-mark showhold | egrep "linux|bananapi")
+
+ # check if eMMC/SD is on the system
+ if [[ $(sed -n 's/^DEVNAME=//p' /sys/dev/block/$(mountpoint -d /)/uevent 2> /dev/null) == mmcblk* \
+ && -f /usr/sbin/nand-sata-install ]]; then
+ LIST+=( "Install" "Install to/update boot loader" )
+ fi
+
+ # bananapi specific function
+ if [[ -f /etc/bananapi-release ]]; then
+ if [[ -n "${mark}" ]]; then
+ :
+ #LIST+=( "Defreeze" "Enable Banana Pi upgrades " )
+ else
+ :
+ #LIST+=( "Freeze" "Disable Banana Pi upgrades " )
+ fi
+ fi
+
+ # bananapi specific function, when upgrades are enabled
+ if [[ -z ${mark} ]]; then
+ [[ -f /etc/apt/sources.list.d/bananapi.list ]] && [[ -n $(grep -w apt /etc/apt/sources.list.d/bananapi.list) ]] \
+ && LIST+=( "Nightly" "Switch to nightly automated builds" )
+ [[ -f /etc/apt/sources.list.d/bananapi.list ]] && [[ -n $(grep -w beta /etc/apt/sources.list.d/bananapi.list) ]] \
+ && LIST+=( "Stable" "Switch to stable builds" )
+ fi
+
+ [[ -n $(grep -w "#kernel.printk" /etc/sysctl.conf ) ]] && LIST+=( "Lowlevel" "Stop low-level messages on console" )
+
+ [[ -f /boot/bananapiEnv.txt ]] && LIST+=( "Bootenv" "Edit boot environment" )
+ [[ -f /boot/boot.ini ]] && LIST+=( "Bootscript" "Edit boot script" )
+
+ if [[ -f /etc/default/cpufrequtils ]]; then
+ LIST+=( "CPU" "Set CPU speed and governor" )
+ fi
+
+ AVAHIDSTATUS=$(service avahi-daemon status 2> /dev/null | grep -w active | grep -w running)
+ if [[ -n "$AVAHIDSTATUS" ]]; then
+ LIST+=( "Avahi" "Disable system announce in the network" )
+ else
+ LIST+=( "Avahi" "Announce system in the network" )
+ fi
+
+ [[ -d ${OVERLAYDIR} ]] && \
+ LIST+=( "Hardware" "Toggle hardware configuration: UART, I2C, etc." )
+ [[ "$LINUXFAMILY" = cubox && "$BRANCH" = "next" ]] && LIST+=( "DTB" "Switch board .dtb configuration" )
+ # this is avaliable only in kernel higher than 4.10
+ testvercomp "$(uname -r | sed 's/-.*//')" "4.10.0" ">"
+ [[ "$LINUXFAMILY" = odroidxu4 && $? == 0 ]] && LIST+=( "DTB" "Select optimised board configuration" )
+ [[ -f /usr/bin/bin2fex && "$LINUXFAMILY" = sun*i && "$BRANCH" = "default" ]] && LIST+=( "Fexedit" "Board (fex) settings editor" )
+
+ [[ -z ${mark} ]] && [[ -f /etc/apt/sources.list.d/bananapi.list ]] && LIST+=( "Other" "Switch to other kernels" )
+
+ LIST+=( "SSH" "Reconfigure SSH daemon" )
+ LIST+=( "Firmware" "Run apt update & apt upgrade" )
+
+ if [[ "$SHELL" != "/bin/bash" ]]; then
+ LIST+=( "BASH" "Revert to stock BASH shell" )
+ else
+ LIST+=( "ZSH" "Install ZSH with plugins and tmux" )
+ fi
+
+
+ [[ "$LINUXFAMILY" = sun*i && "$BRANCH" = "default" && \
+ -n $(bin2fex /dev/null | grep -w "hdmi_used = 1") ]] && LIST+=( "Display" "Set the display resolution" )
+ [[ "$LINUXFAMILY" = odroidc* || "$LINUXFAMILY" = odroidn2 && "$BRANCH" = "default" ]] && LIST+=( "Display" "Set the display resolution" )
+ # desktop
+ if [[ -n $DISPLAY_MANAGER ]]; then
+ LIST+=( "Desktop" "Disable desktop or change login type" )
+ else
+ if [[ -n $DESKTOP_INSTALLED ]]; then
+ LIST+=( "Desktop" "Enable desktop" )
+ else
+ :
+ #LIST+=( "Default" "Install desktop with browser and extras" )
+ fi
+ fi
+
+ # overlayroot
+ if [[ "$DISTRO" == "Ubuntu" && "$(modinfo overlay > /dev/null 2>&1; echo $?)" == "0" ]]; then
+ if [ -n "$(mount | grep -w tmpfs-root)" ]; then
+ :
+ #LIST+=( "Overlayroot" "Disable virtual read-only root filesystem" )
+ else
+ :
+ #LIST+=( "Overlayroot" "Enable virtual read-only root filesystem" )
+ fi
+ fi
+
+ # count number of menu items to adjust window size
+ LISTLENGTH="$((6+${#LIST[@]}/2))"
+ BOXLENGTH=${#LIST[@]}
+ temp_rc=$(mktemp)
+ if [[ -n ${mark} || -n $(grep -w beta /etc/apt/sources.list.d/bananapi.list 2> /dev/null) ]]; then
+ cat <<-'EOF' > $temp_rc
+ dialog_color = (RED,WHITE,OFF)
+ screen_color = (WHITE,RED,ON)
+ tag_color = (RED,WHITE,ON)
+ item_selected_color = (WHITE,RED,ON)
+ tag_selected_color = (WHITE,RED,ON)
+ tag_key_selected_color = (WHITE,RED,ON)
+ EOF
+ [[ -n ${mark} ]] && local sys_title=" Warning - firmware packages frozen"
+ [[ -n $(grep -w beta /etc/apt/sources.list.d/bananapi.list 2> /dev/null) ]] && \
+ local sys_title=" Warning - attached to beta repository"
+ [[ -n ${mark} && -n $(grep -w beta /etc/apt/sources.list.d/bananapi.list 2> /dev/null) ]] && \
+ sys_title=" Warning - frozen & attached to beta repository"
+ else
+ local sys_title=" System settings "
+ echo > $temp_rc
+ fi
+
+if [[ -z $selection ]]; then
+ exec 3>&1
+ selection=$(DIALOGRC=$temp_rc dialog --colors --backtitle "$BACKTITLE" --title " $sys_title " --clear \
+ --cancel-label "Back" --menu "$disclaimer" $LISTLENGTH 0 $BOXLENGTH \
+ "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && break
+fi
+
+ # run main function
+ jobs "$selection"
+done
+}
+
+
+
+
+#
+# menu for networking
+#
+function submenu_networking ()
+{
+
+# select default interface if there is more than one connected
+#select_interface "default"
+unset main
+while true; do
+
+ LIST=()
+ DIALOG_CANCEL=1
+ DIALOG_ESC=255
+
+ # check if we have some LTE modems
+ for i in $(lsusb | awk '{print $6}'); do lte "$i"; done;
+
+ # edit ip
+ LIST+=( "IP" "Select dynamic or edit static IP address" )
+
+ # hostapd
+ HOSTAPDBRIDGE=$(cat /etc/hostapd.conf 2> /dev/null | grep -w "^bridge=br0")
+ HOSTAPDSTATUS=$(service hostapd status 2> /dev/null | grep -w active | grep -w running)
+ if [[ -n "$HOSTAPDSTATUS" ]]; then
+ HOSTAPDINFO=$(hostapd_cli get_config 2> /dev/null | grep ^ssid | sed 's/ssid=//g')
+ HOSTAPDCLIENTS=$(hostapd_cli all_sta 2> /dev/null | grep connected_time | wc -l)
+ LIST+=( "Hotspot" "Manage active wireless access point" )
+ else
+ :
+ [[ -n $(LC_ALL=C nmcli device status 2> /dev/null | grep wifi | grep -w disconnected) ]] && \
+ LIST+=( "Hotspot" "Create WiFi access point" )
+
+ fi
+
+ # toggle IPv6
+ if [[ $(cat /proc/sys/net/ipv6/conf/all/disable_ipv6) == 1 ]]; then
+ LIST+=( "IPV6" "Enable IPv6 for APT and system" )
+ else
+ LIST+=( "IPV6" "Disable IPv6 for APT and system" )
+ fi
+
+ # network throughput test
+ if check_if_installed iperf3; then
+ if pgrep -x "iperf3" > /dev/null
+ then
+ LIST+=( "Iperf3" "Disable network throughput tests daemon" )
+ else
+ LIST+=( "Iperf3" "Enable network throughput tests daemon" )
+ fi
+ fi
+
+ if [[ -n $(LC_ALL=C nmcli device status 2> /dev/null | grep wifi | grep -v unavailable | grep -v unmanaged) ]]; then
+ LIST+=( "WiFi" "Manage wireless networking" )
+ else
+ LIST+=( "Clear" "Clear possible blocked interfaces" )
+ fi
+
+ if [[ -n $LTE_MODEM ]]; then
+ # apply udev rules
+ initialize_lte
+ LIST+=( "LTE" "$LTE_MODEM" )
+ fi
+
+ check_if_installed lirc && LIST+=( "Remove IR" "Remove IR support" ) || LIST+=( "IR" "Install IR support" )
+ if check_if_installed bluetooth then ; then
+ LIST+=( "BT remove" "Remove Bluetooth support" )
+ if [[ -n $(service bluetooth status | grep -w active | grep -w running) ]]; then
+ [[ $(hcitool dev | sed '1d') != "" ]] && LIST+=( "BT discover" "Discover and connect Bluetooth devices" )
+ fi
+ else
+ LIST+=( "BT install" "Install Bluetooth support" )
+ fi
+
+
+
+ [[ -d /usr/local/vpnclient ]] && LIST+=( "VPN" "Manage Softether VPN client" ) && VPNSERVERIP=$(/usr/local/vpnclient/vpncmd /client localhost /cmd accountlist | grep "VPN Server" |grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | head -1)
+
+ LIST+=( "Advanced" "Edit /etc/network/interfaces" )
+ [[ $(ls -1 /etc/NetworkManager/system-connections 2> /dev/null) ]] && \
+ LIST+=( "Forget" "Disconnect and forget all wireless connections" )
+
+ # count number of menu items to adjust window size
+ LISTLENGTH="$((12+${#LIST[@]}/2))"
+ BOXLENGTH=${#LIST[@]}
+ WIFICONNECTED=$(LC_ALL=C nmcli -f NAME,TYPE connection show --active 2> /dev/null | grep wireless | awk 'NF{NF-=1};1')
+
+ local disclaimer=""
+
+ local ipadd=$(ip -4 addr show dev $DEFAULT_ADAPTER | awk '/inet/ {print $2}' | cut -d'/' -f1)
+
+
+ if [[ -n $(LC_ALL=C nmcli device status 2> /dev/null | grep $DEFAULT_ADAPTER | grep connected) ]]; then
+ local ifup="\nIP ($DEFAULT_ADAPTER) via Network Manager: \Z1${ipadd}\n\Z0 "
+ else
+ if [[ -n $(service systemd-networkd status | grep -w active | grep -w running) ]]; then
+ local ifup="\nIP ($DEFAULT_ADAPTER) via systemd-networkd: \Z1${ipadd}\n\Z0 "
+ else
+ local ifup="\nIP ($DEFAULT_ADAPTER) via IFUPDOWN: \Z1${ipadd}\n\Z0 "
+ fi
+ fi
+
+ disclaimer="$ifup"
+
+ if [[ -n $WIFICONNECTED ]]; then
+ LISTLENGTH=$((LISTLENGTH+2))
+ local connected="\n\Z0Connected to SSID: \Z1${WIFICONNECTED}\n\Z0 "
+ disclaimer=$disclaimer"$connected"
+ fi
+
+ if [[ -n $VPNSERVERIP ]]; then
+ local vpnserverip="\n\Z0Connected to VPN server: \Z1${VPNSERVERIP}\n\Z0 "
+ disclaimer=$disclaimer"$vpnserverip"
+ LISTLENGTH=$((LISTLENGTH+2))
+ fi
+
+ if [[ -n $HOSTAPDINFO && -n $HOSTAPDSTATUS ]]; then
+ LISTLENGTH=$((LISTLENGTH+2))
+ chpid=$(dmesg | grep $(grep ^interface /etc/hostapd.conf | sed 's/interface=//g') | head -1 | sed 's/\[.*\]//g' | awk '{print $1}')
+ disclaimer=$disclaimer$"\n\Z0Hotspot SSID: \Z1$HOSTAPDINFO\Zn Band:";
+ if [[ `grep ^hw_mode=a /etc/hostapd.conf` ]]; then local band="5Ghz"; else band="2.4Ghz"; fi
+ if [[ `grep ^ieee80211n /etc/hostapd.conf` ]]; then local type="N"; fi
+ if [[ `grep ^ieee80211ac /etc/hostapd.conf` ]]; then local type="AC"; fi
+ disclaimer=$disclaimer$" \Z1${band} ${type}\Z0"
+ [[ ! "$chpid" =~ .*IPv6.* ]] && disclaimer=$disclaimer$"\n\nChip: \Z1${chpid}\Z0";
+ if [ "$HOSTAPDCLIENTS" -gt "0" ]; then disclaimer=$disclaimer$" Connected clients: \Z1$HOSTAPDCLIENTS\Zn"; fi
+ if [[ ! "$chpid" =~ .*IPv6.* ]]; then LISTLENGTH=$((LISTLENGTH+2)); fi
+ disclaimer=$disclaimer$"\n";
+ fi
+ disclaimer=$disclaimer"\n\Z1Note\Zn: This tool can be successful only when drivers are configured properly. If auto-detection fails, you are on your own.\n "
+
+if [[ -z $selection ]]; then
+ exec 3>&1
+ selection=$(dialog --backtitle "$BACKTITLE" --colors --title " Wired, Wireless, Bluetooth, Hotspot " --clear \
+ --cancel-label "Back" --menu "${disclaimer}" $LISTLENGTH 70 $BOXLENGTH \
+ "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && break
+fi
+ # run main function
+ jobs "$selection"
+
+done
+}
+
+
+
+
+#
+# personal
+#
+function submenu_personal ()
+{
+unset main
+while true; do
+
+ LIST=()
+ LIST+=( "Timezone" "Change timezone \Z5($(LC_ALL=C timedatectl | grep zone | awk '{$1=$1;print}' | sed "s/Time zone: //"))\Z0" )
+ LIST+=( "Locales" "Reconfigure language \Z5($(locale | grep LANGUAGE | cut -d= -f2 | cut -d_ -f1))\Z0 and character set" )
+ LIST+=( "Keyboard" "Change console keyboard layout (\Z5$(cat /etc/default/keyboard | grep XKBLAYOUT | grep -o '".*"' | sed 's/"//g')\Z0)")
+ LIST+=( "Hostname" "Change your hostname \Z5($(cat /etc/hostname))\Z0" )
+ LIST+=( "Welcome" "Toggle welcome screen items" )
+
+ # count number of menu items to adjust window sizee
+ LISTLENGTH="$((6+${#LIST[@]}/2))"
+ BOXLENGTH=${#LIST[@]}
+
+ exec 3>&1
+ selection=$(dialog --colors --backtitle "$BACKTITLE" --title "Personal settings" --clear \
+ --cancel-label "Back" --menu "$disclaimer" $LISTLENGTH 70 $BOXLENGTH \
+ "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && break
+
+ # run main function
+ jobs "$selection"
+
+done
+}
+
+
+
+
+#
+# software
+#
+function submenu_software ()
+{
+unset main
+while true; do
+
+ # detect desktop
+ check_desktop
+
+ LIST=()
+ [[ -f /usr/bin/softy || -f softy ]] && LIST+=( "Softy" "3rd party applications installer" )
+ [[ -f /usr/bin/h3consumption && "$LINUXFAMILY" = "sun8i" && "$BRANCH" = "default" ]] && \
+ LIST+=( "Consumption" "Control board consumption" )
+ [[ -f /usr/bin/bananapimonitor ]] && LIST+=( "Monitor" "Simple CLI board monitoring" )
+ LIST+=( "Benchmarking" "sbc-bench board benchmarking" )
+ [[ -f /usr/bin/bananapimonitor ]] && LIST+=( "Diagnostics" "Send diagnostics" )
+
+ #if [[ -n $(dpkg -l | grep linux-headers) ]]; then LIST+=( "Headers_remove" "kernel headers" ); else \
+ #LIST+=( "Headers_install" "kernel headers" ); fi
+
+ SOURCE_PKG_LIST=$(apt-cache --names-only search ^linux-source-* | awk '{ print $1 }' | grep -w ${BRANCH}-${LINUXFAMILY} | tail -n 5)
+ if [[ -n $SOURCE_PKG_LIST ]]; then
+ :
+ #LIST+=( "Source_install" "kernel source" )
+ fi
+ SOURCE_PKG_LIST_INSTALLED=$(find /usr/src -maxdepth 1 -name "linux-source*")
+ if [[ -n $SOURCE_PKG_LIST_INSTALLED ]]; then
+ :
+ #LIST+=( "Source_remove" "kernel source" );
+ fi
+
+ if [[ -f /etc/bananapi.txt ]]; then
+ if [[ -n $(dpkg -l | grep -w "bananapi-firmware-full ") ]]; then
+ :
+ #LIST+=( "Mini" "Install mini firmware package" );
+ else
+ :
+ #LIST+=( "Full" "Install full firmware package" );
+ fi
+ fi
+
+ if [[ -n $DISPLAY_MANAGER ]]; then
+ if [[ $(service xrdp status 2> /dev/null | grep -w active) ]]; then
+ LIST+=( "RDP" "Disable remote desktop access from Windows" )
+ else
+ LIST+=( "RDP" "Enable remote desktop access from Windows" )
+ fi
+ if ! check_if_installed thunderbird ; then
+ LIST+=( "Thunderbird" "Install full featured email client" )
+ else
+ LIST+=( "Thunderbird" "Remove full featured email client" )
+ fi
+ if ! check_if_installed gimp ; then
+ LIST+=( "Gimp" "Install photo manipulation tool" )
+ else
+ LIST+=( "Gimp" "Remove photo manipulation tool" )
+ fi
+ if ! check_if_installed libreoffice-writer ; then
+ LIST+=( "Writer" "Libreoffice: Writer only" )
+ LIST+=( "Suite" "Libreoffice: Full suite" )
+ else
+ if ! check_if_installed libreoffice-base ; then
+ LIST+=( "Suite" "Libreoffice: Full suite" )
+ LIST+=( "Libre" "Remove Libre office packages" )
+ else
+ LIST+=( "Libre" "Remove Libre office packages" )
+ fi
+ fi
+ fi
+
+ # count number of menu items to adjust window sizee
+ LISTLENGTH="$((6+${#LIST[@]}/2))"
+ BOXLENGTH=${#LIST[@]}
+
+ if [[ -z $selection ]]; then
+ exec 3>&1
+ selection=$(dialog --backtitle "$BACKTITLE" --title "System and 3rd party software" --clear \
+ --cancel-label "Back" --menu "$disclaimer" $LISTLENGTH 70 $BOXLENGTH \
+ "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && break
+ fi
+
+ # run main function
+ jobs "$selection"
+
+done
+}
diff --git a/external/cache/sources/bananapi-config/debian-software b/external/cache/sources/bananapi-config/debian-software
new file mode 100644
index 0000000..81f694a
--- /dev/null
+++ b/external/cache/sources/bananapi-config/debian-software
@@ -0,0 +1,1827 @@
+#!/bin/bash
+#
+# Copyright (c) 2017 Igor Pečovnik, igor.pecovnik@gma**.com
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+# Functions:
+# check_status
+# choose_webserver
+# server_conf
+# install_packet
+# alive_port
+# alive_process
+# install_basic
+# create_ispconfig_configuration
+# check_if_installed
+# install_cups
+# install_samba
+# install_ncp
+# install_omv
+# install_tvheadend
+# install_docker
+# install_urbackup
+# install_transmission
+# install_transmission_seed_bananapi_torrents
+# install_hassio
+# install_openhab
+# install_syncthing
+# install_plex_media_server
+# install_emby_server
+# install_radarr
+# install_sonarr
+# install_vpn_server
+# install_vpn_client
+# install_DashNTP
+# install_MySQL
+# install_MySQLDovecot
+# install_Virus
+# install_hhvm
+# install_phpmyadmin
+# install_apache
+# install_nginx
+# install_PureFTPD
+# install_Bind
+# install_Stats
+# install_Jailkit
+# install_Fail2BanDovecot
+# install_Fail2BanRulesDovecot
+# install_ISPConfig
+
+
+
+
+#
+# load functions, local first
+#
+if [[ -f debian-config-jobs ]]; then source debian-config-jobs;
+ elif [[ -f /usr/lib/bananapi-config/jobs.sh ]]; then \
+ source /usr/lib/bananapi-config/jobs.sh;
+ else exit 1;
+fi
+
+if [[ -f debian-config-submenu ]]; then source debian-config-submenu;
+ elif [[ -f /usr/lib/bananapi-config/submenu.sh ]]; then \
+ source /usr/lib/bananapi-config/submenu.sh;
+ else exit 1;
+fi
+
+if [[ -f debian-config-functions ]]; then source debian-config-functions;
+ elif [[ -f /usr/lib/bananapi-config/functions.sh ]]; then \
+ source /usr/lib/bananapi-config/functions.sh;
+ else exit 1;
+fi
+
+if [[ -f debian-config-functions-network ]]; then source debian-config-functions-network;
+ elif [[ -f /usr/lib/bananapi-config/functions-network.sh ]]; then \
+ source /usr/lib/bananapi-config/functions-network.sh;
+ else exit 1;
+fi
+
+
+
+
+function check_status
+{
+#
+# Check if service is already installed and show it's status
+#
+
+ dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nLoading install info ... " 5 28
+ LIST=()
+ LIST_CONST=26
+
+ # Samba
+ SAMBA_STATUS="$(check_if_installed samba && echo "on" || echo "off" )"
+ alive_port "Windows compatible file sharing" "445" "boolean"
+ LIST+=( "Samba" "$DESCRIPTION" "$SAMBA_STATUS" )
+
+ # CUPS
+ CUPS_STATUS="$(check_if_installed cups && echo "on" || echo "off" )"
+ alive_port "Common UNIX Printing System (CUPS)" "631" "boolean"
+ LIST+=( "CUPS" "$DESCRIPTION" "$CUPS_STATUS" )
+
+ # TV headend
+ TVHEADEND_STATUS="$(check_if_installed tvheadend && echo "on" || echo "off" )"
+ alive_port "TV streaming server" "9981"
+ LIST+=( "TV headend" "$DESCRIPTION" "$TVHEADEND_STATUS" )
+
+ # Synthing
+ SYNCTHING_STATUS="$([[ -f /usr/bin/syncthing ]] && echo "on" || echo "off" )"
+ alive_port "Personal cloud @syncthing.net" "8384"
+ LIST+=( "Syncthing" "$DESCRIPTION" "$SYNCTHING_STATUS" )
+
+ # Hass.io
+ HASS_STATUS="$([[ -f /etc/hassio.json ]] && echo "on" || echo "off" )"
+ alive_port "Home assistant smarthome suite" "8123"
+ #LIST+=( "Hassio" "$DESCRIPTION" "$HASS_STATUS" )
+
+ # OpenHab
+ OPENHAB_STATUS="$([[ -f /usr/bin/openhab-cli ]] && echo "on" || echo "off" )"
+ alive_port "Openhab2 smarthome suite" "8080"
+ LIST+=( "OpenHAB" "$DESCRIPTION" "$OPENHAB_STATUS" )
+
+ # VPN
+ if [[ "$(dpkg --print-architecture)" == "armhf" || "$(dpkg --print-architecture)" == "amd64" ]]; then
+ # vpn server
+ VPN_SERVER_STATUS="$([[ -d /usr/local/vpnserver ]] && echo "on" || echo "off" )"
+ LIST+=( "VPN server" "Softether VPN server" "$VPN_SERVER_STATUS" )
+ # vpn client
+ VPN_CLIENT_STATUS="$([[ -d /usr/local/vpnclient ]] && echo "on" || echo "off" )"
+ LIST+=( "VPN client" "Softether VPN client" "$VPN_CLIENT_STATUS" )
+ LIST_CONST=$((LIST_CONST + 1))
+ fi
+
+ # NCP
+ NCP_STATUS="$( [[ -d /var/www/nextcloud ]] && echo "on" || echo "off" )"
+ alive_port "Nextcloud personal cloud" "443"
+ [[ "$family" != "Ubuntu" ]] && LIST+=( "NCP" "$DESCRIPTION" "$NCP_STATUS" ) \
+ && LIST_CONST=$((LIST_CONST + 1))
+
+ # OMV
+ OMV_STATUS="$(check_if_installed openmediavault && echo "on" || echo "off" )"
+ [[ "$family" != "Ubuntu" ]] && LIST+=( "OMV" "OpenMediaVault NAS solution" "$OMV_STATUS" ) \
+ && LIST_CONST=$((LIST_CONST + 1))
+
+ # Plex media server
+ PLEX_STATUS="$((check_if_installed plexmediaserver || check_if_installed plexmediaserver-installer) \
+ && echo "on" || echo "off" )"
+ alive_port "Plex media server" "32400"
+ LIST+=( "Plex" "$DESCRIPTION" "$PLEX_STATUS" )
+
+ # Emby server
+ AMBY_STATUS="$((check_if_installed emby-server) \
+ && echo "on" || echo "off" )"
+ alive_port "Emby server" "8096"
+ LIST+=( "Emby" "$DESCRIPTION" "$AMBY_STATUS" )
+
+ # Radarr
+ RADARR_STATUS="$([[ -d /opt/Radarr ]] && echo "on" || echo "off" )"
+ alive_port "Movies downloading server" "7878"
+ LIST+=( "Radarr" "$DESCRIPTION" "$RADARR_STATUS" )
+
+ # Sonarr
+ SONARR_STATUS="$([[ -d /opt/NzbDrone ]] && echo "on" || echo "off" )"
+ alive_port "TV shows downloading server" "8989"
+ LIST+=( "Sonarr" "$DESCRIPTION" "$SONARR_STATUS" )
+
+ # MINIdlna
+ MINIDLNA_STATUS="$(check_if_installed minidlna && echo "on" || echo "off" )"
+ alive_port "Lightweight DLNA/UPnP-AV server" "8200" "boolean"
+ LIST+=( "Minidlna" "$DESCRIPTION" "$MINIDLNA_STATUS" )
+
+ # Pi hole
+ PI_HOLE_STATUS="$([[ -d /etc/pihole ]] && echo "on" || echo "off" )"
+ alive_process "Ad blocker" "pihole-FTL"
+ LIST+=( "Pi hole" "$DESCRIPTION" "$PI_HOLE_STATUS" )
+
+ # Transmission
+ TRANSMISSION_STATUS="$(check_if_installed transmission-daemon && echo "on" || echo "off" )"
+ alive_port "Torrent download server" "9091"
+ #LIST+=( "Transmission" "$DESCRIPTION" "$TRANSMISSION_STATUS" )
+
+ # UrBackup
+ URBACKUP_STATUS="$((check_if_installed urbackup-server || check_if_installed urbackup-server-dbg) \
+ && echo "on" || echo "off" )"
+ alive_port "Client/server backup system" "55414"
+ LIST+=( "UrBackup" "$DESCRIPTION" "$URBACKUP_STATUS" )
+
+ # Docker
+ DOCKER_STATUS="$((check_if_installed docker-ce) && echo "on" || echo "off" )"
+ LIST+=( "Docker" "Run applications by using containers" "$DOCKER_STATUS")
+
+ # Mayan EDMS docker install
+ if [[ "$DOCKER_STATUS" == "on" ]]; then
+ curl --output /dev/null --silent --head --fail http://localhost/authentication/login/?next=
+ MAYAN_STATUS=$([[ $? -eq 0 ]] && echo "on" || echo "off")
+ else
+ MAYAN_STATUS="off"
+ fi
+
+ #LIST+=( "Mayan EDMS" "Electronic vault for your documents" "$MAYAN_STATUS")
+
+ # ISPconfig
+ alive_port "SMTP mail, IMAP, POP3 & LAMP/LEMP web server" "8080" "ssl"
+ ISPCONFIG_STATUS="$([[ -d /usr/local/ispconfig ]] && echo "on" || echo "off" )"
+ LIST+=( "ISPConfig" "$DESCRIPTION" "$ISPCONFIG_STATUS" )
+
+ # PHPmyadmin
+# TODO: fix phpmyadmin installer before uncommenting this section
+# if [[ $ISPCONFIG_STATUS == on ]]; then
+# LIST_CONST=$((LIST_CONST + 1))
+# alive_port "MYSQL administration" "8081" "" "/phpmyadmin"
+# PHPMYADMIN_STATUS="on"
+# LIST+=( "PHPmyadmin" "$DESCRIPTION" "$PHPMYADMIN_STATUS" )
+# fi
+}
+
+
+
+
+function choose_webserver
+{
+#
+# Target web server selection
+#
+check_if_installed openmediavault
+case $? in
+ 0)
+ # OMV installed, prevent switching from nginx to apache which would trash OMV installation
+ server="nginx"
+ ;;
+ *)
+ dialog --title "Choose a webserver" --backtitle "$BACKTITLE" --yes-label "Apache" --no-label "Nginx" \
+ --yesno "\nChoose a web server which you are familiar with. They both work almost the same." 8 70
+ response=$?
+ case $response in
+ 0) server="apache";;
+ 1) server="nginx";;
+ 255) exit;;
+ esac
+ ;;
+esac
+}
+
+
+
+
+function server_conf
+{
+#
+# Add some required date for installation
+#
+if [[ "$(curl -s ipinfo.io/ip)" != "$serverIP" ]]; then
+table="\Z2Application Protocol Port\n
+\Z0----------------------------------\n
+FTP TCP 20\n
+FTP TCP 21\n
+SSH/SFTP TCP 22\n
+Mail (SMTP) TCP 25\n
+DNS TCP 53\n
+Web (HTTP) TCP 80\n
+Mail (POP3) TCP 110\n
+Mail (IMAP) TCP 143\n
+Web (HTTPS) TCP 443\n
+Mail (SMTPS) TCP 465\n
+Mail (SMTP) TCP 587\n
+Mail (IMAPS) TCP 993\n
+Mail (POP3S) TCP 995\n
+Database TCP 3306\n
+Chat (XMPP) TCP 5222\n
+ISPConfig TCP 8080\n
+ISPConfig TCP 8081\n
+ISPConfig TCP 10000\n
+DNS UDP 53\n
+Database UDP 3306\n
+";
+dialog --colors --title "Warning" --msgbox "\nYour internal and external IP addresses are different which seems that you are behind a router. \n\nMake sure \Z1$serverIP\Z0 is a static IP address. Then forward external ports to those services which you plan to use.\n\n\n$table" 38 38
+fi
+#
+HOSTNAMEFQDN=$(\
+ dialog --title "Server configuration" \
+ --ok-label "Install" \
+ --backtitle "$BACKTITLE" \
+ --inputbox "\nSet FQDN for $serverIP:" 10 50 \
+ "$(hostname).example.com" \
+ 3>&1 1>&2 2>&3 3>&- \
+)
+# create random password for mysql
+MYSQL_PASS=$(< /dev/urandom tr -dc A-Z-a-z-0-9 | head -c16)
+}
+
+
+
+
+install_packet ()
+{
+#
+# Install missing packets
+#
+i=0
+j=1
+IFS=" "
+declare -a PACKETS=($1)
+#skupaj=$(apt-get -s -y -qq install $1 | wc -l)
+skupaj=${#PACKETS[@]}
+while [[ $i -lt $skupaj ]]; do
+ procent=$(echo "scale=2;($j/$skupaj)*100"|bc)
+ x=${PACKETS[$i]}
+ if [ $(dpkg-query -W -f='${Status}' $x 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
+ printf '%.0f\n' $procent | dialog \
+ --backtitle "$BACKTITLE" \
+ --title "Installing" \
+ --gauge "\n$2\n\n$x" 10 70
+ if [ "$(DEBIAN_FRONTEND=noninteractive apt-get -qq -y install $x >${TEMP_DIR}/install.log 2>&1 || echo 'Installation failed' \
+ | grep 'Installation failed')" != "" ]; then
+ echo -e "[\e[0;31m error \x1B[0m] Installation failed"
+ tail ${TEMP_DIR}/install.log
+ exit
+ fi
+ fi
+ i=$[$i+1]
+ j=$[$j+1]
+done
+echo ""
+}
+
+
+
+
+alive_port ()
+{
+#
+# Displays URL to the service $1 on port $2 or just that is active if $3 = boolean $4 = path
+#
+if [[ -n $(netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".'$2'"') ]]; then
+ if [[ $3 == boolean ]]; then
+ DESCRIPTION="$1 is \Z1active\Z0";
+ elif [[ $3 == ssl ]]; then
+ DESCRIPTION="Active on https://${serverIP}:\Z1$2\Z0$4";
+ else
+ DESCRIPTION="Active on http://${serverIP}:\Z1$2\Z0$4";
+ fi
+else
+ DESCRIPTION="$1";
+fi
+}
+
+
+
+
+alive_process ()
+{
+#
+# check if process name $2 is running. Display it's name $1 or $1 is active if active
+#
+if pgrep -x "$2" > /dev/null 2>&1; then DESCRIPTION="$1 is \Z1active\Z0"; else DESCRIPTION="$1"; fi
+}
+
+
+
+
+install_basic (){
+#
+# Set hostname, FQDN, add to sources list
+#
+IFS=" "
+set ${HOSTNAMEFQDN//./ }
+HOSTNAMESHORT="$1"
+cp /etc/hosts /etc/hosts.backup
+cp /etc/hostname /etc/hostname.backup
+# create new
+echo "127.0.0.1 localhost.localdomain localhost" > /etc/hosts
+echo "${serverIP} ${HOSTNAMEFQDN} ${HOSTNAMESHORT} #ispconfig " >> /etc/hosts
+echo "$HOSTNAMESHORT" > /etc/hostname
+/etc/init.d/hostname.sh start >/dev/null 2>&1
+hostnamectl set-hostname $HOSTNAMESHORT
+if [[ $family == "Ubuntu" ]]; then
+ # set hostname in Ubuntu
+ hostnamectl set-hostname $HOSTNAMESHORT
+ # disable AppArmor
+ if [[ -n $(service apparmor status 2> /dev/null | grep -w active | grep -w running) ]]; then
+ service apparmor stop
+ update-rc.d -f apparmor remove
+ apt-get -y -qq remove apparmor apparmor-utils
+ fi
+else
+ grep -q "contrib" /etc/apt/sources.list || sed -i 's|main|main contrib|' /etc/apt/sources.list
+ grep -q "non-free" /etc/apt/sources.list || sed -i 's|contrib|contrib non-free|' /etc/apt/sources.list
+ grep -q "deb http://ftp.debian.org/debian jessie-backports main" /etc/apt/sources.list || echo "deb http://ftp.debian.org/debian jessie-backports main" >> /etc/apt/sources.list
+ debconf-apt-progress -- apt-get update
+fi
+}
+
+
+
+
+create_ispconfig_configuration (){
+#
+# ISPConfig autoconfiguration
+#
+cat > ${TEMP_DIR}/isp.conf.php <
+EOF
+}
+
+
+
+install_cups ()
+{
+#
+# Install printer system
+#
+#debconf-apt-progress -- apt-get update
+#debconf-apt-progress -- apt-get -y install cups lpr cups-filters
+apt-get update >/dev/null 2>&1
+apt-get -y install cups lpr cups-filters >/dev/null 2>&1
+# cups-filters if jessie
+sed -e 's/Listen localhost:631/Listen 631/g' -i /etc/cups/cupsd.conf
+sed -e 's//\nallow $SUBNET/g' -i /etc/cups/cupsd.conf
+sed -e 's//\nallow $SUBNET/g' -i /etc/cups/cupsd.conf
+sed -e 's//\nallow $SUBNET/g' -i /etc/cups/cupsd.conf
+service cups restart
+service samba restart | service smbd restart >/dev/null 2>&1
+}
+
+
+
+
+install_samba ()
+{
+#
+# install Samba file sharing
+#
+local SECTION="Samba"
+SMBUSER=$(whiptail --inputbox "What is your samba username?" 8 78 $SMBUSER --title "$SECTION" 3>&1 1>&2 2>&3)
+exitstatus=$?; if [ $exitstatus = 1 ]; then exit 1; fi
+SMBPASS=$(whiptail --inputbox "What is your samba password?" 8 78 $SMBPASS --title "$SECTION" 3>&1 1>&2 2>&3)
+exitstatus=$?; if [ $exitstatus = 1 ]; then exit 1; fi
+SMBGROUP=$(whiptail --inputbox "What is your samba group?" 8 78 $SMBGROUP --title "$SECTION" 3>&1 1>&2 2>&3)
+exitstatus=$?; if [ $exitstatus = 1 ]; then exit 1; fi
+#
+debconf-apt-progress -- apt-get update
+debconf-apt-progress -- apt-get -y install samba samba-common-bin samba-vfs-modules
+useradd $SMBUSER
+echo -ne "$SMBPASS\n$SMBPASS\n" | passwd $SMBUSER >/dev/null 2>&1
+echo -ne "$SMBPASS\n$SMBPASS\n" | smbpasswd -a -s $SMBUSER >/dev/null 2>&1
+service samba stop | service smbd stop >/dev/null 2>&1
+cp /etc/samba/smb.conf /etc/samba/smb.conf.stock
+cat > /etc/samba/smb.conf.tmp << EOF
+[global]
+ workgroup = SMBGROUP
+ server string = %h server
+ hosts allow = SUBNET
+ log file = /var/log/samba/log.%m
+ max log size = 1000
+ syslog = 0
+ panic action = /usr/share/samba/panic-action %d
+ load printers = yes
+ printing = cups
+ printcap name = cups
+ min receivefile size = 16384
+ write cache size = 524288
+ getwd cache = yes
+ socket options = TCP_NODELAY IPTOS_LOWDELAY
+
+[printers]
+ comment = All Printers
+ path = /var/spool/samba
+ browseable = no
+ public = yes
+ guest ok = yes
+ writable = no
+ printable = yes
+ printer admin = SMBUSER
+
+[print$]
+ comment = Printer Drivers
+ path = /etc/samba/drivers
+ browseable = yes
+ guest ok = no
+ read only = yes
+ write list = SMBUSER
+
+[ext]
+ comment = Storage
+ path = /ext
+ browseable = yes
+ writable = yes
+ public = no
+ valid users = SMBUSER
+ force create mode = 0644
+EOF
+sed -i "s/SMBGROUP/$SMBGROUP/" /etc/samba/smb.conf.tmp
+sed -i "s/SMBUSER/$SMBUSER/" /etc/samba/smb.conf.tmp
+sed -i "s/SUBNET/$SUBNET/" /etc/samba/smb.conf.tmp
+dialog --backtitle "$BACKTITLE" --title "Review samba configuration" --no-collapse --editbox /etc/samba/smb.conf.tmp 30 0 2> /etc/samba/smb.conf.tmp.out
+if [[ $? = 0 ]]; then
+ mv /etc/samba/smb.conf.tmp.out /etc/samba/smb.conf
+ install -m 755 -g $SMBUSER -o $SMBUSER -d /ext
+ echo -ne "$SMBPASS\n$SMBPASS\n" | smbpasswd -a -s $SMBUSER >/dev/null 2>&1
+ service smbd stop >/dev/null 2>&1
+ sleep 3
+ service smbd start >/dev/null 2>&1
+fi
+}
+
+
+
+install_ncp (){
+ curl -sSL https://raw.githubusercontent.com/nextcloud/nextcloudpi/master/install.sh > ${TEMP_DIR}/install.sh
+ curl -sSL https://raw.githubusercontent.com/nextcloud/nextcloudpi/master/etc/ncp.cfg > ${TEMP_DIR}/ncp.cfg
+ local DEBIAN_RELEASE=$(awk '{if ($1 == "\"release\":" ) {print $2}}' ${TEMP_DIR}/ncp.cfg | sed 's/[", ]//g')
+ sed "s/check_distro etc\/ncp.cfg/[[ \$(lsb_release -cs) == \"${DEBIAN_RELEASE}\" ]] /" -i ${TEMP_DIR}/install.sh
+ bash ${TEMP_DIR}/install.sh
+}
+
+
+
+install_omv (){
+#
+# Install OpenMediaVault on Debian
+#
+if [ -f /etc/bananapi-release ]; then
+ . /etc/bananapi-release
+fi
+
+# Don't allow installation on Ubuntu
+if [[ "$family" == "Ubuntu" ]]; then
+ dialog --backtitle "$BACKTITLE" --title "Dependencies not met" --msgbox "\nOpenMediaVault can only be installed on Debian." 7 52
+ sleep 5
+ exit 1
+fi
+
+# Warning / Notice before install
+case $distribution in
+ wheezy|jessie)
+ dialog --backtitle "$BACKTITLE" --title "OMV3 is End of Life" --msgbox "\nUpgrade to a supported OS : Debian Stretch or Buster." 7 52
+ sleep 5
+ exit 1
+ ;;
+esac
+
+# Download OMV install script
+wgeturl="https://github.com/OpenMediaVault-Plugin-Developers/installScript/raw/master/install"
+fancy_wget "$wgeturl" "-O ${TEMP_DIR}/omv_install.sh"
+
+# Remove Crony on Stretch since OMV4 depends on NTP
+if [[ "$distribution" == "stretch" ]]; then
+ apt-get -y -qq remove chrony
+fi
+
+# Execute install script
+echo "Now installing OpenMediaVault. Be patient, it will take several minutes..."
+bash ${TEMP_DIR}/omv_install.sh &>> /var/log/omv_install.log
+
+# Board Specific Tweak
+echo "Now applying board tweak if required..."
+
+# Hardkernel Cloudshell 1 and 2 fixes, read the whole thread for details:
+# https://forum.openmediavault.org/index.php/Thread/17855
+lsusb | grep -q -i "05e3:0735" && sed -i "/exit 0/i echo 20 > /sys/class/block/sda/queue/max_sectors_kb" /etc/rc.local
+
+case ${BOARD} in
+ odroidxu4)
+ HMP_Fix='; taskset -c -p 4-7 $i '
+ apt install -y i2c-tools
+ /usr/sbin/i2cdetect -y 1 | grep -q "60: 60"
+ if [ $? -eq 0 ]; then
+ add-apt-repository -y ppa:kyle1117/ppa
+ sed -i 's/jessie/xenial/' /etc/apt/sources.list.d/kyle1117-ppa-jessie.list
+ apt install -y -q cloudshell-lcd odroid-cloudshell cloudshell2-fan &
+ lsusb -v | awk -F"__" '/RANDOM_/ {print $2}' | head -n1 | while read ; do
+ echo "ATTRS{idVendor}==\"152d\", ATTRS{idProduct}==\"0561\", KERNEL==\"sd*\", ENV{DEVTYPE}==\"disk\", SYMLINK=\"disk/by-id/\$env{ID_BUS}-CloudShell2-${REPLY}-\$env{ID_MODEL}\"" >> /etc/udev/rules.d/99-cloudshell2.rules
+ echo "ATTRS{idVendor}==\"152d\", ATTRS{idProduct}==\"0561\", KERNEL==\"sd*\", ENV{DEVTYPE}==\"partition\", SYMLINK=\"disk/by-id/\$env{ID_BUS}-CloudShell2-${REPLY}-\$env{ID_MODEL}-part%n\"" >> /etc/udev/rules.d/99-cloudshell2.rules
+ done
+ fi
+ ;;
+ helios4)
+ # Make mdadm display fault events on Fault LED
+ # NOTE : this is not a permanent approach need to be improved via some OMV core code change
+ if [ -f /usr/sbin/mdadm-fault-led.sh ]; then
+ if [[ "$distribution" == "stretch" ]]; then
+ sed -i -e "/HOMEHOST/a \\\n# Trigger Fault Led script when an event is detected\\nPROGRAM \/usr\/sbin\/mdadm-fault-led.sh" /usr/share/openmediavault/mkconf/mdadm
+ /usr/sbin/omv-mkconf mdadm
+ elif [[ "$distribution" == "buster" ]]; then
+ cat < /srv/salt/omv/deploy/mdadm/25faultled.sls
+mdadm_add_program_config:
+ cmd.run:
+ - name: "echo -e '\n# Trigger Fault Led script when an event is detected\nPROGRAM /usr/sbin/mdadm-fault-led.sh' >> /etc/mdadm/mdadm.conf"
+EOF
+ /usr/sbin/omv-salt deploy run mdadm
+ fi
+ fi
+ ;;
+esac
+}
+
+install_tvheadend ()
+{
+#
+# TVheadend https://tvheadend.org/ unofficial port https://tvheadend.org/boards/5/topics/21528
+#
+if [[ "$family" == "Ubuntu" ]]; then
+ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 26F4EF8440618B66 >/dev/null 2>&1
+ add-apt-repository -y ppa:mamarley/tvheadend-git-stable >/dev/null 2>&1
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get -y install libssl-doc libssl1.0.0 zlib1g-dev tvheadend xmltv-util
+else
+ if [ ! -f /etc/apt/sources.list.d/tvheadend.list ]; then
+ echo "deb https://www.deb-multimedia.org ${distribution} main non-free" >> /etc/apt/sources.list.d/tvheadend.list
+ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 5C808C2B65558117 >/dev/null 2>&1
+ fi
+ URL="https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.0.0_1.0.1t-1+deb8u9_"$(dpkg --print-architecture)".deb"
+ fancy_wget "$URL" "-O ${TEMP_DIR}/package.deb"
+ dpkg -i ${TEMP_DIR}/package.deb >/dev/null 2>&1
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get -y install libssl-doc zlib1g-dev tvheadend xmltv-util
+fi
+}
+
+
+
+
+install_docker ()
+{
+
+#echo "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/${family,,} $distribution edge" >\
+# /etc/apt/sources.list.d/docker.list
+#curl -fsSL "https://download.docker.com/linux/${family,,}/gpg" | apt-key add -qq - > /dev/null 2>&1
+
+echo "deb [arch=$(dpkg --print-architecture)] https://mirrors.aliyun.com/docker-ce/linux/${family,,} $distribution edge" >\
+/etc/apt/sources.list.d/docker.list
+
+curl -fsSL "https://mirrors.aliyun.com/docker-ce/linux/${family,,}/gpg" | apt-key add -qq - > /dev/null 2>&1
+
+debconf-apt-progress -- apt-get update
+debconf-apt-progress -- apt-get install -y -qq --no-install-recommends docker-ce
+}
+
+
+
+
+install_urbackup ()
+{
+#
+# Client/server backup system https://www.urbackup.org/
+#
+if [ "$(dpkg --print-architecture | grep arm64)" == "arm64" ]; then local arch=armhf; else local arch=$(dpkg --print-architecture); fi
+PREFIX="https://hndl.urbackup.org/Server/latest/"
+URL="https://hndl.urbackup.org/Server/latest/"$(wget -q $PREFIX -O - | html2text -width 120 | grep deb | awk ' { print $3 }' | grep $arch)
+fancy_wget "$URL" "-O ${TEMP_DIR}/package.deb"
+dpkg -i ${TEMP_DIR}/package.deb >/dev/null 2>&1
+apt-get -yy -f install
+}
+
+
+
+
+install_transmission ()
+{
+#
+# transmission
+#
+install_packet "debconf-utils unzip build-essential html2text apt-transport-https" "Downloading dependencies"
+install_packet "transmission-cli transmission-common transmission-daemon" "Install torrent server"
+service transmission-daemon stop
+local A=(${serverIP//./ })
+local servernetwork="${A[0]}.${A[1]}.*.*"
+sed "s/\"rpc-whitelist\": \"127.0.0.1.*/\"rpc-whitelist\": \"127.0.0.1,$servernetwork\",/" -i /etc/transmission-daemon/settings.json
+service transmission-daemon start
+# systemd workaround
+# https://forum.armbian.com/index.php?/topic/4017-programs-does-not-start-automatically-at-boot/
+sed -e 's/exit 0//g' -i /etc/rc.local
+cat >> /etc/rc.local <<"EOF"
+service transmission-daemon restart
+exit 0
+EOF
+}
+
+
+
+install_transmission_seed_bananapi_torrents ()
+{
+#
+# seed our torrents
+#
+# adjust network buffers if necessary
+rmem_recommended=4194304
+wmem_recommended=1048576
+rmem_actual=$(sysctl net.core.rmem_max | awk -F" " '{print $3}')
+if [ ${rmem_actual} -lt ${rmem_recommended} ]; then
+ grep -q net.core.rmem_max /etc/sysctl.conf && \
+ sed -i "s/net.core.rmem_max =.*/net.core.rmem_max = ${rmem_recommended}/" /etc/sysctl.conf || \
+ echo "net.core.rmem_max = ${rmem_recommended}" >> /etc/sysctl.conf
+fi
+wmem_actual=$(sysctl net.core.wmem_max | awk -F" " '{print $3}')
+if [ ${wmem_actual} -lt ${wmem_recommended} ]; then
+ grep -q net.core.wmem_max /etc/sysctl.conf && \
+ sed -i "s/net.core.wmem_max =.*/net.core.wmem_max = ${wmem_recommended}/" /etc/sysctl.conf || \
+ echo "net.core.wmem_max = ${wmem_recommended}" >> /etc/sysctl.conf
+fi
+/sbin/sysctl -p >/dev/null 2>&1
+# create cron job for daily sync with official Armbian torrents
+cat > /etc/cron.daily/seed-armbian-torrent <<"EOF"
+#!/bin/bash
+#
+# armbian torrents auto update
+#
+# download latest torrent pack
+TEMP_DIR=$(mktemp -d || exit 1)
+chmod 700 ${TEMP_DIR}
+trap "rm -rf \"${TEMP_DIR}\" ; exit 0" 0 1 2 3 15
+wget -qO- -O ${TEMP_DIR}/armbian-torrents.zip https://dl.armbian.com/torrent/all-torrents.zip
+# test zip for corruption
+unzip -t ${TEMP_DIR}/armbian-torrents.zip >/dev/null 2>&1
+[[ $? -ne 0 ]] && echo "Error in zip" && exit
+# extract zip
+unzip -o ${TEMP_DIR}/armbian-torrents.zip -d ${TEMP_DIR}/torrent-tmp >/dev/null 2>&1
+# create list of current active torrents
+transmission-remote -n 'transmission:transmission' -l | sed '1d; $d' > ${TEMP_DIR}/torrent-tmp/active.torrents
+# loop and add/update torrent files
+for f in ${TEMP_DIR}/torrent-tmp/*.torrent; do
+ transmission-remote -n 'transmission:transmission' -a $f > /dev/null 2>&1
+ # remove added from the list
+ pattern="${f//.torrent}"; pattern="${pattern##*/}";
+ sed -i "/$pattern/d" ${TEMP_DIR}/torrent-tmp/active.torrents
+done
+# remove old armbian torrents
+while read i; do
+ [[ $i == *Armbian_* || $i == *gcc-linaro-* || $i == *tar.lz4 ]] && transmission-remote -n 'transmission:transmission' -t $(echo "$i" | awk '{print $1}';) --remove-and-delete
+done < ${TEMP_DIR}/torrent-tmp/active.torrents
+# remove temporally files and direcotories
+EOF
+chmod +x /etc/cron.daily/seed-armbian-torrent
+/etc/cron.daily/seed-armbian-torrent &
+}
+
+
+
+
+install_hassio ()
+{
+#
+# Install Home assistant smart home suite hass.io / Docker instance by using official installer
+#
+
+local arch=$(dpkg --print-architecture)
+
+case $arch in
+ armhf)
+ local machine=raspberrypi2
+ ;;
+ arm64)
+ local machine=raspberrypi4-64
+ ;;
+ amd64)
+ local machine=intel-nuc
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+
+if [ $? == 0 ]; then
+
+ install_docker
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get install -y apparmor-utils apt-transport-https avahi-daemon ca-certificates \
+ dbus jq network-manager socat software-properties-common
+ #curl -sL "https://raw.githubusercontent.com/home-assistant/supervised-installer/master/installer.sh" | \
+ #bash -s -- -m ${machine}
+ curl -sL "https://gitee.com/leeboby/supervised-installer/raw/master/installer.sh" | \
+ bash -s -- -m ${machine}
+ dialog --backtitle "$BACKTITLE" --title "Please wait" \
+ --msgbox "\nIt can take several minutes before Home Assistant UI becomes available! " 7 75
+
+fi
+}
+
+
+
+
+install_openhab ()
+{
+#
+# Install Openhab2 smart home suite openhab.org
+#
+
+# Install ZuluJDK
+#
+# test below
+#
+# sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0xB1998361219BD9C9
+# sudo apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'
+# apt install zulu-embedded-8
+
+
+local jdkArch=$(dpkg --print-architecture)
+
+case $jdkArch in
+
+ armhf)
+ URL="https://cdn.azul.com/zulu-embedded/bin/zulu8.40.0.178-ca-jdk1.8.0_222-linux_aarch32hf.tar.gz"
+ ;;
+ arm64)
+ URL="https://cdn.azul.com/zulu-embedded/bin/zulu8.40.0.178-ca-jdk1.8.0_222-linux_aarch64.tar.gz"
+ ;;
+ amd64)
+ URL="https://cdn.azul.com/zulu/bin/zulu8.42.0.21-ca-jdk8.0.232-linux_x64.tar.gz"
+ ;;
+ *)
+ URL="https://cdn.azul.com/zulu/bin/zulu8.42.0.21-ca-jdk8.0.232-linux_i686.tar.gz"
+
+esac
+
+fancy_wget "$URL" "-O ${TEMP_DIR}/zulu8.tar.gz"
+mkdir -p /opt/jdk
+tar -xpzf ${TEMP_DIR}/zulu8.tar.gz -C /opt/jdk
+jdkBin=$(find /opt/jdk/*/bin ... -print -quit)
+jdkLib=$(find /opt/jdk/*/lib ... -print -quit)
+update-alternatives --remove-all java >/dev/null 2>&1
+update-alternatives --remove-all javac >/dev/null 2>&1
+update-alternatives --install /usr/bin/java java "$jdkBin"/java 1083000 >/dev/null 2>&1
+update-alternatives --install /usr/bin/javac javac "$jdkBin"/javac 1083000 >/dev/null 2>&1
+echo "$jdkLib"/"$jdkArch" > /etc/ld.so.conf.d/java.conf
+echo "$jdkLib"/"$jdkArch"/jli >> /etc/ld.so.conf.d/java.conf
+ldconfig >/dev/null 2>&1
+wget -qO - 'https://bintray.com/user/downloadSubjectPublicKey?username=openhab' | apt-key add - >/dev/null 2>&1
+echo 'deb https://dl.bintray.com/openhab/apt-repo2 stable main' | tee /etc/apt/sources.list.d/openhab2.list >/dev/null 2>&1
+debconf-apt-progress -- apt-get update
+debconf-apt-progress -- apt-get install -y openhab2
+systemctl daemon-reload >/dev/null 2>&1
+systemctl enable openhab2.service >/dev/null 2>&1
+systemctl start openhab2.service >/dev/null 2>&1
+# addons seems broken
+# apt-get install -y openhab2-addons
+sed -i 's|EXTRA_JAVA_OPTS=""|EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0:/dev/ttyS0:/dev/ttyS2:/dev/ttyACM0:/dev/ttyAMA0"|' /etc/default/openhab2
+service openhab2 restart >/dev/null 2>&1
+dialog --backtitle "$BACKTITLE" --title "Please wait" --msgbox \
+"\nIt can take several minutes before OpenHAB UI becomes available! " 7 68
+}
+
+
+
+
+install_syncthing ()
+{
+#
+# Install Personal cloud https://syncthing.net/
+#
+
+curl -s https://syncthing.net/release-key.txt | apt-key add - >/dev/null 2>&1
+echo "deb https://apt.syncthing.net/ syncthing stable" | tee /etc/apt/sources.list.d/syncthing.list >/dev/null 2>&1
+debconf-apt-progress -- apt-get update
+debconf-apt-progress -- apt-get -y install syncthing
+
+# increase open file limit
+if !(grep -qs "fs.inotify.max_user_watches=204800" "/etc/sysctl.conf");then
+ echo -e "fs.inotify.max_user_watches=204800" | tee -a /etc/sysctl.conf
+fi
+add_choose_user
+mv /lib/systemd/system/syncthing@.service /lib/systemd/system/syncthing@${CHOSEN_USER}.service
+
+# create startup files
+systemctl enable syncthing@${CHOSEN_USER}.service >/dev/null 2>&1
+systemctl start syncthing@${CHOSEN_USER}.service >/dev/null 2>&1
+systemctl stop syncthing@${CHOSEN_USER}.service >/dev/null 2>&1
+systemctl start syncthing@${CHOSEN_USER}.service >/dev/null 2>&1
+# wait until config file is created
+while :
+do
+ if [[ -f /home/${CHOSEN_USER}/.config/syncthing/config.xml ]]; then break; fi
+ sleep 1
+done
+# change to server IP
+sed -i "s/127.0.0.1/${serverIP}/" /home/${CHOSEN_USER}/.config/syncthing/config.xml
+systemctl restart syncthing@${CHOSEN_USER}.service >/dev/null 2>&1
+dialog --backtitle "$BACKTITLE" --title "Please wait" --msgbox "\nIt can take several minutes before Syncthing UI becomes available! " 7 70
+}
+
+
+
+
+install_plex_media_server ()
+{
+#
+# Plex Media server
+#
+ echo -e "deb https://downloads.plex.tv/repo/deb public main" > /etc/apt/sources.list.d/plex.list
+ wget -q -O - https://downloads.plex.tv/plex-keys/PlexSign.key | apt-key add - >/dev/null 2>&1
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get -y install plexmediaserver
+}
+
+
+
+
+install_emby_server ()
+{
+#
+# Emby server
+#
+ ARCH=$(dpkg --print-architecture)
+ #URL=$(curl -s https://api.github.com/repos/MediaBrowser/Emby.Releases/releases/latest | grep "/emby-server-deb.*${ARCH}.deb" | cut -d : -f 2,3 | tr -d \")
+ #URL=https://gitee.com/leeboby/embyreleases/raw/master/emby-server-deb_4.5.2.0_${ARCH}.deb
+ #fancy_wget "$URL" "-O ${TEMP_DIR}/emby.deb"
+ git clone https://gitee.com/leeboby/embyreleases.git /tmp/emby >/dev/null 2>&1
+ dpkg -i /tmp/emby/emby-server-deb_4.5.2.0_${ARCH}.deb >/dev/null 2>&1
+ apt-get -yy -f install
+ rm -rf /tmp/emby
+}
+
+
+
+
+install_radarr ()
+{
+#
+# Automatically downloading movies
+#
+debconf-apt-progress -- apt-get update
+debconf-apt-progress -- apt-get -y install mono-devel mediainfo libmono-cil-dev
+#wgeturl=$(curl -s "https://api.github.com/repos/Radarr/Radarr/releases" | grep 'linux.tar.gz' | grep 'browser_download_url' | head -1 | cut -d \" -f 4)
+#fancy_wget "$wgeturl" "-O ${TEMP_DIR}/radarr.tgz"
+git clone -b radarr https://gitee.com/leeboby/software.git /tmp/radarr >/dev/null 2>&1
+cp /tmp/radarr/Radarr*linux.tar.gz /tmp/radarr/radarr.tgz
+tar xf /tmp/radarr/radarr.tgz -C /opt
+cat << _EOF_ > /etc/systemd/system/radarr.service
+[Unit]
+Description=Radarr Daemon
+After=network.target
+[Service]
+User=root
+Type=simple
+ExecStart=/usr/bin/mono --debug /opt/Radarr/Radarr.exe -nobrowser
+[Install]
+WantedBy=multi-user.target
+_EOF_
+systemctl enable radarr >/dev/null 2>&1
+systemctl start radarr
+}
+
+
+
+
+install_sonarr ()
+{
+#
+# Automatically downloading TV shows
+#
+if [ "$(dpkg --print-architecture | grep arm64)" == "arm64" ]; then
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get -y install mono-complete mediainfo
+ fancy_wget "https://update.sonarr.tv/v2/develop/mono/NzbDrone.develop.tar.gz" "-O ${TEMP_DIR}/sonarr.tgz"
+ tar xf ${TEMP_DIR}/sonarr.tgz -C /opt
+else
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0xA236C58F409091A18ACA53CBEBFF6B99D9B78493 >/dev/null 2>&1
+ echo -e "deb http://apt.sonarr.tv/ master main" | sudo tee /etc/apt/sources.list.d/sonarr.list
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get -y install nzbdrone
+fi
+cat << _EOF_ > /etc/systemd/system/sonarr.service
+[Unit]
+Description=Sonarr (NzbDrone) Daemon
+After=network.target
+[Service]
+User=root
+Type=simple
+ExecStart=/usr/bin/mono --debug /opt/NzbDrone/NzbDrone.exe -nobrowser
+[Install]
+WantedBy=multi-user.target
+_EOF_
+systemctl enable sonarr >/dev/null 2>&1
+systemctl start sonarr
+}
+
+
+
+
+install_vpn_server ()
+{
+#
+# Script downloads latest stable
+#
+cd ${TEMP_DIR}
+#PREFIX="https://www.softether-download.com/files/softether/"
+install_packet "debconf-utils unzip build-essential html2text apt-transport-https" "Downloading basic packages"
+#URL=$(wget -q $PREFIX -O - | html2text | grep rtm | awk ' { print $(NF) }' | tail -1)
+#SUFIX="${URL/-tree/}"
+#if [ "$(dpkg --print-architecture | grep armhf)" != "" ]; then
+#DLURL=$PREFIX$URL"/Linux/SoftEther_VPN_Server/32bit_-_ARM_EABI/softether-vpnserver-$SUFIX-linux-arm_eabi-32bit.tar.gz"
+#else
+#install_packet "gcc-multilib" "Install libraries"
+#DLURL=$PREFIX$URL"/Linux/SoftEther_VPN_Server/32bit_-_Intel_x86/softether-vpnserver-$SUFIX-linux-x86-32bit.tar.gz"
+#fi
+#wget -q $DLURL -O - | tar -xz
+git clone -b vpnserver --depth=1 https://gitee.com/leeboby/software.git /tmp/vpnserver >/dev/null 2>&1
+cd /tmp/vpnserver
+tar -zxf *.tar.gz
+cd vpnserver
+make i_read_and_agree_the_license_agreement | dialog --backtitle "$BACKTITLE" --title "Compiling SoftEther VPN" --progressbox $TTY_Y $TTY_X
+cd ..
+cp -R vpnserver /usr/local
+cd /usr/local/vpnserver/
+chmod 600 *
+chmod 700 vpncmd
+chmod 700 vpnserver
+if [[ -d /run/systemd/system/ ]]; then
+cat </lib/systemd/system/ethervpn.service
+[Unit]
+Description=VPN service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/vpnserver/vpnserver start
+ExecStop=/usr/local/vpnserver/vpnserver stop
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
+EOT
+systemctl enable ethervpn.service
+service ethervpn start
+
+else
+
+cat < /etc/init.d/vpnserver
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: vpnserver
+# Required-Start: \$remote_fs \$syslog
+# Required-Stop: \$remote_fs \$syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Start daemon at boot time
+# Description: Enable Softether by daemon.
+### END INIT INFO
+DAEMON=/usr/local/vpnserver/vpnserver
+LOCK=/var/lock/vpnserver
+test -x $DAEMON || exit 0
+case "\$1" in
+start)
+\$DAEMON start
+touch \$LOCK
+;;
+stop)
+\$DAEMON stop
+rm \$LOCK
+;;
+restart)
+\$DAEMON stop
+sleep 3
+\$DAEMON start
+;;
+*)
+echo "Usage: \$0 {start|stop|restart}"
+exit 1
+esac
+exit 0
+EOT
+chmod 755 /etc/init.d/vpnserver
+mkdir /var/lock/subsys
+update-rc.d vpnserver defaults >> $logfile
+/etc/init.d/vpnserver start
+fi
+}
+
+
+
+
+install_vpn_client ()
+{
+#
+# Script downloads latest stable
+#
+#cd ${TEMP_DIR}
+#PREFIX="https://www.softether-download.com/files/softether/"
+install_packet "debconf-utils unzip build-essential html2text apt-transport-https" "Downloading basic packages"
+#URL=$(wget -q $PREFIX -O - | html2text | grep rtm | awk ' { print $(NF) }' | tail -1)
+#SUFIX="${URL/-tree/}"
+#if [ "$(dpkg --print-architecture | grep armhf)" != "" ]; then
+# DLURL=$PREFIX$URL"/Linux/SoftEther_VPN_Client/32bit_-_ARM_EABI/softether-vpnclient-$SUFIX-linux-arm_eabi-32bit.tar.gz"
+#else
+# install_packet "gcc-multilib" "Install libraries"
+# DLURL=$PREFIX$URL"/Linux/SoftEther_VPN_Client/32bit_-_Intel_x86/softether-vpnclient-$SUFIX-linux-x86-32bit.tar.gz"
+#fi
+#wget -q $DLURL -O - | tar -xz
+git clone -b vpnclient --depth=1 https://gitee.com/leeboby/software.git /tmp/vpnclient >/dev/null 2>&1
+cd /tmp/vpnclient
+tar -zxf *.tar.gz
+cd vpnclient
+make i_read_and_agree_the_license_agreement | dialog --backtitle "$BACKTITLE" --title "Compiling SoftEther VPN vpnclient" --progressbox $TTY_Y $TTY_X
+cd ..
+cp -R vpnclient /usr/local
+cd /usr/local/vpnclient/
+chmod 600 *
+chmod 700 vpncmd
+chmod 700 vpnclient
+}
+
+
+
+
+install_DashNTP ()
+{
+#
+# Install DASH and NTP service
+#
+echo "dash dash/sh boolean false" | debconf-set-selections
+dpkg-reconfigure -f noninteractive dash > /dev/null 2>&1
+install_packet "ntp ntpdate" "Install DASH and NTP service"
+}
+
+
+
+
+install_MySQL ()
+{
+#
+# Maria SQL
+#
+install_packet "mariadb-client mariadb-server" "SQL client and server"
+#Allow MySQL to listen on all interfaces
+cp /etc/mysql/my.cnf /etc/mysql/my.cnf.backup
+[[ -f /etc/mysql/my.cnf ]] && sed -i 's|bind-address.*|#bind-address = 127.0.0.1|' /etc/mysql/my.cnf
+[[ -f /etc/mysql/mariadb.conf.d/50-server.cnf ]] && sed -i 's|bind-address.*|#bind-address = 127.0.0.1|' /etc/mysql/mariadb.conf.d/50-server.cnf
+SECURE_MYSQL=$(expect -c "
+set timeout 3
+spawn mysql_secure_installation
+expect \"Enter current password for root (enter for none):\"
+send \"\r\"
+expect \"root password?\"
+send \"y\r\"
+expect \"New password:\"
+send \"$MYSQL_PASS\r\"
+expect \"Re-enter new password:\"
+send \"$MYSQL_PASS\r\"
+expect \"Remove anonymous users?\"
+send \"y\r\"
+expect \"Disallow root login remotely?\"
+send \"y\r\"
+expect \"Remove test database and access to it?\"
+send \"y\r\"
+expect \"Reload privilege tables now?\"
+send \"y\r\"
+expect eof
+")
+#
+# Execution mysql_secure_installation
+#
+echo "${SECURE_MYSQL}" >> /dev/null
+# ISP config exception
+mkdir -p /etc/mysql/mariadb.conf.d/
+cat > /etc/mysql/mariadb.conf.d/99-ispconfig.cnf<<"EOF"
+[mysqld]
+sql-mode="NO_ENGINE_SUBSTITUTION"
+EOF
+service mysql restart >> /dev/null
+}
+
+
+
+
+install_MySQLDovecot ()
+{
+#
+# Install Postfix, Dovecot, Saslauthd, rkhunter, binutils
+#
+echo "postfix postfix/main_mailer_type select Internet Site" | debconf-set-selections
+echo "postfix postfix/mailname string $HOSTNAMEFQDN" | debconf-set-selections
+install_packet "postfix postfix-mysql postfix-doc openssl getmail4 rkhunter binutils dovecot-imapd dovecot-pop3d dovecot-mysql \
+dovecot-sieve sudo libsasl2-modules dovecot-lmtpd" "postfix, dovecot, saslauthd, rkhunter, binutils"
+#Uncommenting some Postfix configuration files
+cp /etc/postfix/master.cf /etc/postfix/master.cf.backup
+sed -i 's|#submission inet n - - - - smtpd|submission inet n - - - - smtpd|' /etc/postfix/master.cf
+sed -i 's|# -o syslog_name=postfix/submission| -o syslog_name=postfix/submission|' /etc/postfix/master.cf
+sed -i 's|# -o smtpd_tls_security_level=encrypt| -o smtpd_tls_security_level=encrypt|' /etc/postfix/master.cf
+sed -i 's|# -o smtpd_sasl_auth_enable=yes| -o smtpd_sasl_auth_enable=yes|' /etc/postfix/master.cf
+sed -i 's|# -o smtpd_client_restrictions=permit_sasl_authenticated,reject| -o smtpd_client_restrictions=permit_sasl_authenticated,reject|' /etc/postfix/master.cf
+sed -i 's|# -o smtpd_sasl_auth_enable=yes| -o smtpd_sasl_auth_enable=yes|' /etc/postfix/master.cf
+sed -i 's|# -o smtpd_sasl_auth_enable=yes| -o smtpd_sasl_auth_enable=yes|' /etc/postfix/master.cf
+sed -i 's|# -o smtpd_sasl_auth_enable=yes| -o smtpd_sasl_auth_enable=yes|' /etc/postfix/master.cf
+sed -i 's|#smtps inet n - - - - smtpd|smtps inet n - - - - smtpd|' /etc/postfix/master.cf
+sed -i 's|# -o syslog_name=postfix/smtps| -o syslog_name=postfix/smtps|' /etc/postfix/master.cf
+sed -i 's|# -o smtpd_tls_wrappermode=yes| -o smtpd_tls_wrappermode=yes|' /etc/postfix/master.cf
+service postfix restart >> /dev/null
+}
+
+
+
+
+install_Virus ()
+{
+#
+# Install Amavisd-new, SpamAssassin, And ClamAV
+#
+packets="amavisd-new spamassassin clamav clamav-daemon unzip bzip2 arj p7zip unrar-free rpm nomarch lzop \
+cabextract apt-listchanges libnet-ldap-perl libauthen-sasl-perl clamav-docs daemon libio-string-perl libio-socket-ssl-perl \
+libnet-ident-perl zip libnet-dns-perl postgrey"
+if [[ $distribution != "bionic" ]] && [[ $distribution != "buster" ]]; then
+ packets=$packets" zoo"
+fi
+if [[ $distribution != "buster" ]]; then packets=$packets" ripole"; fi
+install_packet "$packets" "amavisd, spamassassin, clamav"
+sed -i "s/^AllowSupplementaryGroups.*/AllowSupplementaryGroups true/" /etc/clamav/clamd.conf
+service spamassassin stop >/dev/null 2>&1
+systemctl disable spamassassin >/dev/null 2>&1
+# amavisd-new program has currently a bug in Ubuntu 18.04
+if [[ $distribution == bionic ]]; then
+ cd ${TEMP_DIR}
+ wget -q https://git.ispconfig.org/ispconfig/ispconfig3/raw/stable-3.1/helper_scripts/ubuntu-amavisd-new-2.11.patch
+ cd /usr/sbin
+ cp -pf amavisd-new amavisd-new_bak
+ patch --silent < ${TEMP_DIR}/ubuntu-amavisd-new-2.11.patch >> /dev/null 2>&1
+fi
+freshclam >> /var/log/ispconfig_config.log
+service clamav-daemon start >/dev/null 2>&1
+}
+
+
+
+
+install_hhvm ()
+{
+#
+# Install HipHop Virtual Machine
+#
+apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94 >/dev/null 2>&1
+add-apt-repository https://dl.hhvm.com/"${family,,}" >/dev/null 2>&1
+debconf-apt-progress -- apt-get update
+install_packet "hhvm" "HipHop Virtual Machine"
+}
+
+
+
+
+install_phpmyadmin ()
+{
+#
+# Phpmyadmin unattended installation
+#
+if [[ "$family" != "Ubuntu" ]]; then
+ debconf-apt-progress -- apt-get update
+ DEBIAN_FRONTEND=noninteractive debconf-apt-progress -- apt-get -y install phpmyadmin
+else
+ debconf-set-selections <<< "phpmyadmin phpmyadmin/internal/skip-preseed boolean true"
+ debconf-set-selections <<< "phpmyadmin phpmyadmin/reconfigure-webserver multiselect true"
+ debconf-set-selections <<< "phpmyadmin phpmyadmin/dbconfig-install boolean false"
+ echo "phpmyadmin phpmyadmin/internal/skip-preseed boolean true" | debconf-set-selections
+ echo "phpmyadmin phpmyadmin/reconfigure-webserver multiselect" | debconf-set-selections
+ echo "phpmyadmin phpmyadmin/dbconfig-install boolean false" | debconf-set-selections
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get install -y phpmyadmin
+fi
+# Apache2 needs additional hack
+WWW_RECONFIG=$(expect -c "
+set timeout 3
+spawn dpkg-reconfigure -f readline phpmyadmin
+expect \"Reinstall database for phpmyadmin?\"
+send \"No\r\"
+expect \"Web server to reconfigure automatically:\"
+send \"1\r\"
+expect eof
+")
+echo "${WWW_RECONFIG}" >> /dev/null
+}
+
+
+
+
+install_apache ()
+{
+#
+# Install Apache2, PHP5, FCGI, suExec, Pear and mcrypt
+#
+
+local pkg="apache2 apache2-doc apache2-utils libapache2-mod-fcgid php-pear mcrypt imagemagick libruby libapache2-mod-python memcached"
+
+local pkg_xenial="libapache2-mod-php php7.0 php7.0-common php7.0-gd php7.0-mysql php7.0-imap php7.0-cli php7.0-cgi \
+apache2-suexec-pristine php-auth php7.0-mcrypt php7.0-curl php7.0-intl php7.0-pspell php7.0-recode php7.0-sqlite3 php7.0-tidy \
+php7.0-xmlrpc php7.0-xsl php-memcache php-imagick php-gettext php7.0-zip php7.0-mbstring php7.0-opcache php-apcu \
+libapache2-mod-fastcgi php7.0-fpm"
+
+local pkg_bionic="apache2 apache2-doc apache2-utils libapache2-mod-php php7.2 php7.2-common php7.2-gd php7.2-mysql php7.2-imap \
+phpmyadmin php7.2-cli php7.2-cgi libapache2-mod-fcgid apache2-suexec-pristine php-pear mcrypt imagemagick libruby libapache2-mod-python \
+php7.2-curl php7.2-intl php7.2-pspell php7.2-recode php7.2-sqlite3 php7.2-tidy php7.2-xmlrpc php7.2-xsl memcached php-memcache \
+php-imagick php-gettext php7.2-zip php7.2-mbstring php-soap php7.2-soap php7.2-fpm php-apcu certbot"
+
+local pkg_stretch="libapache2-mod-php php7.0 php7.0-common php7.0-gd php7.0-mysql php7.0-imap php7.0-cli php7.0-cgi libapache2-mod-fcgid \
+apache2-suexec-pristine php7.0-mcrypt libapache2-mod-python php7.0-curl php7.0-intl php7.0-pspell php7.0-recode php7.0-sqlite3 \
+php7.0-tidy php7.0-xmlrpc php7.0-xsl php-memcache php-imagick php-gettext php7.0-zip php7.0-mbstring libapache2-mod-passenger \
+php7.0-soap php7.0-fpm php7.0-opcache php-apcu certbot"
+
+local pkg_jessie="apache2.2-common apache2-mpm-prefork libexpat1 ssl-cert libapache2-mod-php5 php5 php5-common php5-gd php5-mysql \
+php5-imap php5-cli php5-cgi libapache2-mod-fcgid apache2-suexec php-pear php-auth php5-mcrypt mcrypt php5-imagick libapache2-mod-python \
+php5-curl php5-intl php5-memcache php5-memcached php5-pspell php5-recode php5-sqlite php5-tidy php5-xmlrpc php5-xsl \
+libapache2-mod-passenger php5-xcache libapache2-mod-fastcgi php5-fpm"
+
+local pkg_buster="apache2 apache2-doc apache2-utils libapache2-mod-php php7.3 php7.3-common php7.3-gd php7.3-mysql php7.3-imap \
+php7.3-cli php7.3-cgi libapache2-mod-fcgid apache2-suexec-pristine php-pear mcrypt imagemagick libruby libapache2-mod-python \
+php7.3-curl php7.3-intl php7.3-pspell php7.3-recode php7.3-sqlite3 php7.3-tidy php7.3-xmlrpc php7.3-xsl memcached php-memcache \
+php-imagick php-gettext php7.3-zip php7.3-mbstring php-soap php7.3-soap php7.3-fpm php-apcu certbot"
+
+local temp="pkg_${distribution}"
+install_packet "${pkg} ${!temp}" "Apache for $family $distribution"
+# fix HTTPOXY vulnerability
+cat < /etc/apache2/conf-available/httpoxy.conf
+
+ RequestHeader unset Proxy early
+
+
+EOT
+
+a2enmod actions proxy_fcgi setenvif fastcgi alias httpoxy suexec rewrite ssl actions include dav_fs dav auth_digest cgi headers >/dev/null 2>&1
+ case $distribution in
+ jessie)
+ a2enconf php5-fpm >/dev/null 2>&1
+ ;;
+ xenial)
+ a2enconf php7.0-fpm >/dev/null 2>&1
+ ;;
+ stretch)
+ a2enconf php7.0-fpm >/dev/null 2>&1
+ ;;
+ bionic)
+ a2enconf php7.2-fpm >/dev/null 2>&1
+ ;;
+ buster)
+ a2enconf php7.3-fpm >/dev/null 2>&1
+ ;;
+ esac
+service apache2 restart >> /dev/null
+}
+
+
+
+
+install_nginx ()
+{
+#
+# Install NginX, PHP5, FCGI, suExec, Pear, And mcrypt
+#
+local pkg="nginx php-pear memcached fcgiwrap"
+
+local pkg_xenial="php7.0-fpm php7.0-opcache php7.0-fpm php7.0 php7.0-common php7.0-gd php7.0-mysql php7.0-imap php7.0-cli php7.0-cgi \
+php7.0-mcrypt mcrypt imagemagick libruby php7.0-curl php7.0-intl php7.0-pspell php7.0-recode php7.0-sqlite3 php7.0-tidy \
+php7.0-xmlrpc php7.0-xsl php-memcache php-imagick php-gettext php7.0-zip php7.0-mbstring php-apcu letsencrypt"
+
+local pkg_stretch="php7.0-fpm php7.0-opcache php7.0-fpm php7.0 php7.0-common php7.0-gd php7.0-mysql php7.0-imap php7.0-cli php7.0-cgi \
+php7.0-mcrypt mcrypt imagemagick libruby php7.0-curl php7.0-intl php7.0-pspell php7.0-recode php7.0-sqlite3 php7.0-tidy \
+php7.0-xmlrpc php7.0-xsl php-memcache php-imagick php-gettext php7.0-zip php7.0-mbstring php-apcu letsencrypt"
+
+local pkg_jessie="php5-fpm php5-mysql php5-curl php5-gd php5-intl php5-imagick php5-imap php5-mcrypt php5-memcache \
+php5-memcached php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl php-apc"
+
+local pkg_bionic="php7.2-fpm php7.2-opcache php7.2-fpm php7.2 php7.2-common php7.2-gd php7.2-mysql php7.2-imap php7.2-cli php7.2-cgi \
+imagemagick libruby php7.2-curl php7.2-intl php7.2-pspell php7.2-recode php7.2-sqlite3 php7.2-tidy \
+php7.2-xmlrpc php7.2-xsl php-memcache php-imagick php-gettext php7.2-zip php7.2-mbstring php-apcu letsencrypt"
+
+local pkg_buster="php7.3-fpm php7.3-opcache php7.3-fpm php7.3 php7.3-common php7.3-gd php7.3-mysql php7.3-imap php7.3-cli php7.3-cgi \
+imagemagick libruby php7.3-curl php7.3-intl php7.3-pspell php7.3-recode php7.3-sqlite3 php7.3-tidy \
+php7.3-xmlrpc php7.3-xsl php-memcache php-imagick php-gettext php7.3-zip php7.3-mbstring php-apcu letsencrypt"
+
+local temp="pkg_${distribution}"
+install_packet "${pkg} ${!temp}" "Nginx for $family $distribution"
+
+case $distribution in
+ jessie)
+ phpenmod mcrypt mbstring
+ debconf-apt-progress -- apt-get update
+ debconf-apt-progress -- apt-get install -y python-certbot -t jessie-backports
+ service php5-fpm reload >> /dev/null
+ ;;
+ xenial)
+ phpenmod mcrypt mbstring
+ tz=$(cat /etc/timezone | sed 's/\//\\\//g')
+ sed -i "s/^cgi.fix_pathinfo=.*/cgi.fix_pathinfo=0/" /etc/php/7.0/fpm/php.ini
+ sed -i "s/^date.timezone=.*/date.timezone=""$tz""/" /etc/php/7.0/fpm/php.ini
+ service php7.0-fpm reload >> /dev/null
+ ;;
+ stretch)
+ tz=$(cat /etc/timezone | sed 's/\//\\\//g')
+ sed -i "s/^cgi.fix_pathinfo=.*/cgi.fix_pathinfo=0/" /etc/php/7.0/fpm/php.ini
+ sed -i "s/^date.timezone=.*/date.timezone=""$tz""/" /etc/php/7.0/fpm/php.ini
+ service php7.0-fpm reload >> /dev/null
+ phpenmod mcrypt mbstring
+ ;;
+ bionic)
+ tz=$(cat /etc/timezone | sed 's/\//\\\//g')
+ sed -i "s/^cgi.fix_pathinfo=.*/cgi.fix_pathinfo=0/" /etc/php/7.2/fpm/php.ini
+ sed -i "s/^date.timezone=.*/date.timezone=""$tz""/" /etc/php/7.2/fpm/php.ini
+ service php7.2-fpm reload >> /dev/null
+ phpenmod mbstring
+ ;;
+ buster)
+ tz=$(cat /etc/timezone | sed 's/\//\\\//g')
+ sed -i "s/^cgi.fix_pathinfo=.*/cgi.fix_pathinfo=0/" /etc/php/7.3/fpm/php.ini
+ sed -i "s/^date.timezone=.*/date.timezone=""$tz""/" /etc/php/7.3/fpm/php.ini
+ service php7.3-fpm reload >> /dev/null
+ phpenmod mbstring
+ ;;
+ esac
+}
+
+
+
+
+install_PureFTPD ()
+{
+#
+# Install PureFTPd and Quota
+#
+install_packet "pure-ftpd-common pure-ftpd-mysql quota quotatool" "pureFTPd and Quota"
+
+sed -i 's/VIRTUALCHROOT=false/VIRTUALCHROOT=true/' /etc/default/pure-ftpd-common
+echo 1 > /etc/pure-ftpd/conf/TLS
+mkdir -p /etc/ssl/private/
+openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -subj "/C=GB/ST=GB/L=GB/O=GB/OU=GB/CN=$(hostname -f)/emailAddress=joe@joe.com" -keyout /etc/ssl/private/pure-ftpd.pem -out /etc/ssl/private/pure-ftpd.pem >/dev/null 2>&1
+chmod 600 /etc/ssl/private/pure-ftpd.pem
+/etc/init.d/pure-ftpd-mysql restart >/dev/null 2>&1
+local temp=$(cat /etc/fstab | grep "/ " | tail -1 | awk '{print $4}')
+sed -i "s/$temp/$temp,usrjquota=quota.user,grpjquota=quota.group,jqfmt=vfsv0/" /etc/fstab
+mount -o remount / >/dev/null 2>&1
+quotacheck -avugm >/dev/null 2>&1
+quotaon -avug >/dev/null 2>&1
+}
+
+
+
+
+install_Bind ()
+{
+#
+# Install BIND DNS Server
+#
+install_packet "bind9 dnsutils haveged" "Install BIND DNS Server"
+systemctl enable haveged >/dev/null 2>&1
+systemctl start haveged >/dev/null 2>&1
+}
+
+
+
+
+install_Stats ()
+{
+#
+# Install Vlogger, Webalizer, And AWstats
+#
+install_packet "vlogger webalizer awstats geoip-database libclass-dbi-mysql-perl" "vlogger, webalizer, awstats"
+sed -i "s/MAILTO=root/#MAILTO=root/" /etc/cron.d/awstats
+sed -i "s/*/10 * * * * www-data/#*/10 * * * * www-data/" /etc/cron.d/awstats
+sed -i "s/10 03 * * * www-data/#10 03 * * * www-data/" /etc/cron.d/awstats
+}
+
+
+
+
+install_Jailkit()
+{
+#
+debconf-apt-progress -- apt-get update
+debconf-apt-progress -- apt-get install -y build-essential autoconf automake libtool flex bison debhelper binutils
+cd ${TEMP_DIR}
+wget -q https://olivier.sessink.nl/jailkit/jailkit-2.19.tar.gz -O - | tar -xz && cd jailkit-2.19
+echo 5 > debian/compat
+./debian/rules binary > /dev/null 2>&1
+dpkg -i ../jailkit_2.19-1_*.deb > /dev/null 2>&1
+}
+
+
+
+
+install_Fail2BanDovecot()
+{
+#
+# Install fail2ban
+#
+install_packet "fail2ban ufw" "Install fail2ban and UFW Firewall"
+if [[ $distribution == "stretch" ]]; then
+cat > /etc/fail2ban/jail.local <<"EOF"
+[pure-ftpd]
+enabled = true
+port = ftp
+filter = pure-ftpd
+logpath = /var/log/syslog
+maxretry = 3
+
+[dovecot]
+enabled = true
+filter = dovecot
+logpath = /var/log/mail.log
+maxretry = 5
+
+[postfix-sasl]
+enabled = true
+port = smtp
+filter = postfix-sasl
+logpath = /var/log/mail.log
+maxretry = 3
+EOF
+else
+cat > /etc/fail2ban/jail.local <<"EOF"
+[pureftpd]
+enabled = true
+port = ftp
+filter = pureftpd
+logpath = /var/log/syslog
+maxretry = 3
+
+[dovecot-pop3imap]
+enabled = true
+filter = dovecot-pop3imap
+action = iptables-multiport[name=dovecot-pop3imap, port="pop3,pop3s,imap,imaps", protocol=tcp]
+logpath = /var/log/mail.log
+maxretry = 5
+
+[sasl]
+enabled = true
+port = smtp
+filter = postfix-sasl
+logpath = /var/log/mail.log
+maxretry = 3
+EOF
+fi
+}
+
+
+
+
+install_Fail2BanRulesDovecot()
+{
+#
+# Dovecot rules
+#
+cat > /etc/fail2ban/filter.d/pureftpd.conf <<"EOF"
+[Definition]
+failregex = .*pure-ftpd: \(.*@\) \[WARNING\] Authentication failed for user.*
+ignoreregex =
+EOF
+
+cat > /etc/fail2ban/filter.d/dovecot-pop3imap.conf <<"EOF"
+[Definition]
+failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=(?P\S*),.*
+ignoreregex =
+EOF
+# Add the missing ignoreregex line
+echo "ignoreregex =" >> /etc/fail2ban/filter.d/postfix-sasl.conf
+service fail2ban restart >> /dev/null
+}
+
+
+
+
+install_ISPConfig (){
+#
+# Install ISPConfig 3
+#
+cd ${TEMP_DIR}
+wget -q https://www.ispconfig.org/downloads/ISPConfig-3-stable.tar.gz -O - | tar -xz
+cd ${TEMP_DIR}/ispconfig3_install/install/
+php -q install.php --autoinstall=${TEMP_DIR}/isp.conf.php &>> /var/log/ispconfig_config.log
+dialog --colors --backtitle "$BACKTITLE" --no-collapse --title " Auto updating SSL certificate " --clear --yesno "\nDo you want to secure ISPConfig control panel and all services with free Let's Encrypt SSL certificate?" 8 80
+if [[ $? == 0 ]]; then
+ dialog --colors --backtitle "$BACKTITLE" --no-collapse --title " Instructions " --clear --msgbox "\n1. Access admin panel with your browser: \Z1https://$serverIP:8080\Z0\n\nUsername: \Z1admin\Z0\nPassword: \Z11234\Z0 \n\n\n2. Go to Sites > Website > \Z1Add new website\Z0\n\nDomain: \Z1$(hostname -f)\Z0\nAuto-Subdomain: \Z1None\Z0\nSSL: \Z1enable\Z0\nLet's Encrypt SSL: \Z1enable\Z0\n\n\n3. Go to Tools > \Z1Password and language\Z0\n\nChange ISPConfig control panel password.\n\nSave and Logout. \n\n\n4. Wait until SSL is not working here: \Z1https://$(hostname -f)\Z0 \n\nIt can take up to a few minutes.\n\n\n5. Proceed with install (\Z1Press ENTER\Z0):" 33 80
+ curl -sSL https://github.com/ahrasis/LE4ISPC/archive/master.zip > master.zip 2> /dev/null
+ unzip -qq master.zip
+ bash LE4ISPC-master/${server}/le4ispc.sh 2>&1
+fi
+}
+
+
+
+
+
+#
+# Main choices
+#
+
+# check for root
+#
+if [[ $EUID != 0 ]]; then
+ dialog --title "Warning" --infobox "\nThis script requires root privileges.\n\nExiting ..." 7 41
+ sleep 3
+ exit
+fi
+
+# nameserver backup
+if [ -d /etc/resolvconf/resolv.conf.d ]; then
+ echo 'nameserver 8.8.8.8' > /etc/resolvconf/resolv.conf.d/head
+ resolvconf -u &> /dev/null
+fi
+
+# Create a safe temporary directory
+TEMP_DIR=$(mktemp -d || exit 1)
+chmod 700 ${TEMP_DIR}
+trap "rm -rf \"${TEMP_DIR}\" ; exit 0" 0 1 2 3 15
+
+# Install basic stuff, we have to wait for other apt tasks to finish
+# (eg unattended-upgrades)
+i=0
+tput sc
+while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
+ case $(($i % 4)) in
+ 0 ) j="-" ;;
+ 1 ) j="\\" ;;
+ 2 ) j="|" ;;
+ 3 ) j="/" ;;
+ esac
+ tput rc
+ echo -en "\r[$j] Waiting for other software managers to finish..."
+ sleep 0.5
+ ((i=i+1))
+done
+
+apt-get -qq -y --no-install-recommends install curl debconf-utils html2text apt-transport-https dialog whiptail lsb-release bc expect > /dev/null
+
+# gather some info
+#
+TTY_X=$(($(stty size | awk '{print $2}')-6)) # determine terminal width
+TTY_Y=$(($(stty size | awk '{print $1}')-6)) # determine terminal height
+distribution=$(lsb_release -cs)
+family=$(lsb_release -is)
+DEFAULT_ADAPTER=$(ip -4 route ls | grep default | tail -1 | grep -Po '(?<=dev )(\S+)')
+serverIP=$(ip -4 addr show dev $DEFAULT_ADAPTER | awk '/inet/ {print $2}' | cut -d'/' -f1)
+set ${serverIP//./ }
+SUBNET="$1.$2.$3."
+hostnamefqdn=$(hostname -f)
+mysql_pass=""
+BACKTITLE="Softy - Orange Pi post deployment scripts, https://banana-pi.org"
+SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+#check_status
+
+# main dialog routine
+#
+DIALOG_CANCEL=1
+DIALOG_ESC=255
+
+while true; do
+
+ # prepare menu items
+ check_status
+ LISTLENGTH="$((${#LIST[@]}/2))"
+ exec 3>&1
+ selection=$(dialog --backtitle "$BACKTITLE" --title "Installing to $family $distribution" --colors --clear --cancel-label \
+ "Cancel" --ok-label "Install" --checklist "\nChoose what you want to install:\n " $LIST_CONST 71 18 "${LIST[@]}" 2>&1 1>&3)
+ exit_status=$?
+ exec 3>&-
+ case $exit_status in
+ $DIALOG_ESC | $DIALOG_CANCEL)
+ clear
+ exit 1
+ ;;
+ esac
+
+ # cycle through all install options
+ i=0
+if ! is_package_manager_running; then
+ while [ "$i" -lt "$LISTLENGTH" ]; do
+
+ if [[ "$selection" == *Samba* && "$SAMBA_STATUS" != "on" ]]; then
+ install_samba
+ selection=${selection//Samba/}
+ fi
+
+ if [[ "$selection" == *CUPS* && "$CUPS_STATUS" != "on" ]]; then
+ install_cups
+ selection=${selection//CUPS/}
+ fi
+
+ if [[ "$selection" == *headend* && "$TVHEADEND_STATUS" != "on" ]]; then
+ install_tvheadend
+ selection=${selection//\"TV headend\"/}
+ fi
+
+ if [[ "$selection" == *Minidlna* && "$MINIDLNA_STATUS" != "on" ]]; then
+ install_packet "minidlna" "Install lightweight DLNA/UPnP-AV server"
+ selection=${selection//Minidlna/}
+ fi
+
+ if [[ "$selection" == *ISPConfig* && "$ISPCONFIG_STATUS" != "on" ]]; then
+ debconf-apt-progress -- apt-get update
+ server_conf
+ if [[ "$MYSQL_PASS" == "" ]]; then
+ dialog --msgbox "Mysql password can't be blank. Exiting..." 7 70
+ exit
+ fi
+ if [[ "$(echo $HOSTNAMEFQDN | grep -P '(?=^.{1,254}$)(^(?>(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)')" == "" ]]; then
+ dialog --msgbox "Invalid FQDN. Exiting..." 7 70
+ exit
+ fi
+ choose_webserver; install_basic; install_DashNTP; install_MySQL; install_MySQLDovecot; install_Virus; install_$server;
+ install_phpmyadmin
+ [[ -z "$(dpkg --print-architecture | grep arm)" ]] && install_hhvm
+ create_ispconfig_configuration;install_PureFTPD;install_Stats;install_Bind;
+ install_Jailkit; install_Fail2BanDovecot; install_Fail2BanRulesDovecot;
+ install_ISPConfig
+ selection=${selection//ISPConfig/}
+ fi
+
+ if [[ "$selection" == *Syncthing* && "$SYNCTHING_STATUS" != "on" ]]; then
+ install_syncthing
+ selection=${selection//Syncthing/}
+ fi
+
+ if [[ "$selection" == *Hassio* && "$HASS_STATUS" != "on" ]]; then
+ install_hassio
+ selection=${selection//Hassio/}
+ fi
+
+ if [[ "$selection" == *OpenHAB* && "$OPENHAB_STATUS" != "on" ]]; then
+ install_openhab
+ selection=${selection//OpenHAB/}
+ fi
+
+ if [[ "$selection" == *server* && "$VPN_SERVER_STATUS" != "on" ]]; then
+ install_vpn_server
+ selection=${selection//\"VPN server\"/}
+ fi
+
+ if [[ "$selection" == *client* && "$VPN_CLIENT_STATUS" != "on" ]]; then
+ install_vpn_client
+ selection=${selection//\"VPN client\"/}
+ fi
+ if [[ "$selection" == *NCP* && "$NCP_STATUS" != "on" ]]; then
+ install_ncp
+ selection=${selection//NCP/}
+ fi
+
+ if [[ "$selection" == *OMV* && "$OMV_STATUS" != "on" ]]; then
+ install_omv
+ selection=${selection//OMV/}
+ fi
+
+ if [[ "$selection" == *Plex* && "$PLEX_STATUS" != "on" ]]; then
+ install_plex_media_server
+ selection=${selection//Plex/}
+ fi
+
+ if [[ "$selection" == *Emby* && "$EMBY_STATUS" != "on" ]]; then
+ install_emby_server
+ selection=${selection//Emby/}
+ fi
+
+ if [[ "$selection" == *Radarr* && "$RADARR_STATUS" != "on" ]]; then
+ install_radarr
+ selection=${selection//Radarr/}
+ fi
+
+ if [[ "$selection" == *Sonarr* && "$SONARR_STATUS" != "on" ]]; then
+ install_sonarr
+ selection=${selection//Sonarr/}
+ fi
+
+ if [[ "$selection" == *hole* && "$PI_HOLE_STATUS" != "on" ]]; then
+ #curl -L "https://install.pi-hole.net" | bash
+ export PIHOLE_SKIP_OS_CHECK=true
+ curl -L "https://gitee.com/leeboby/pi-hole/raw/master/automated%20install/basic-install.sh" | bash
+ selection=${selection//\"Pi hole\"/}
+ fi
+
+ if [[ "$selection" == *Docker* && "$DOCKER_STATUS" != "on" ]]; then
+ install_docker
+ selection=${selection//Docker/}
+ fi
+
+ if [[ "$selection" == *Transmission* && "$TRANSMISSION_STATUS" != "on" ]]; then
+ install_transmission
+ selection=${selection//Transmission/}
+ dialog --title "Seed Armbian torrents" --backtitle "$BACKTITLE" --yes-label "Yes" --no-label "No" --yesno "\
+ \nDo you want to help the community and seed armbian torrent files? It will ensure faster downloads for everyone.\
+ \n\nApproximately 400GB disk space is required." 11 44
+ if [[ $? = 0 ]]; then
+ install_transmission_seed_bananapi_torrents
+ fi
+ fi
+
+ if [[ "$selection" == *UrBackup* && "$URBACKUP_STATUS" != "on" ]]; then
+ install_urbackup
+ selection=${selection//UrBackup/}
+ fi
+
+ if [[ "$selection" == *Mayan* && "$MAYAN_STATUS" != "on" ]]; then
+ if [[ "$DOCKER_STATUS" == "off" ]]; then
+ install_docker
+ fi
+ curl -fsSL https://get.mayan-edms.com | bash
+ selection=${selection//Mayan/}
+ fi
+
+ i=$[$i+1]
+ done
+
+fi
+
+ # reread statuses
+ check_status
+done
diff --git a/external/cache/sources/bananapi-config/scripts/smb.conf b/external/cache/sources/bananapi-config/scripts/smb.conf
new file mode 100644
index 0000000..426fbbd
--- /dev/null
+++ b/external/cache/sources/bananapi-config/scripts/smb.conf
@@ -0,0 +1,37 @@
+[global]
+ workgroup = SMBGROUP
+ server string = %h server
+ hosts allow = SUBNET
+ log file = /var/log/samba/log.%m
+ max log size = 1000
+ syslog = 0
+ panic action = /usr/share/samba/panic-action %d
+ load printers = yes
+ printing = cups
+ printcap name = cups
+
+[printers]
+ comment = All Printers
+ path = /var/spool/samba
+ browseable = no
+ public = yes
+ guest ok = yes
+ writable = no
+ printable = yes
+ printer admin = SMBUSER
+
+[print$]
+ comment = Printer Drivers
+ path = /etc/samba/drivers
+ browseable = yes
+ guest ok = no
+ read only = yes
+ write list = SMBUSER
+
+[ext]
+ comment = Storage
+ path = /ext
+ writable = yes
+ public = no
+ valid users = SMBUSER
+ force create mode = 0777
diff --git a/external/cache/sources/bananapi-config/scripts/tv_grab_file b/external/cache/sources/bananapi-config/scripts/tv_grab_file
new file mode 100644
index 0000000..bfc68d1
--- /dev/null
+++ b/external/cache/sources/bananapi-config/scripts/tv_grab_file
@@ -0,0 +1,55 @@
+#!/bin/bash
+dflag=
+vflag=
+cflag=
+if (( $# < 1 ))
+then
+ ### URL of your XML file
+ wget -qO - "http://xml.tv.data"
+ exit 0
+fi
+
+for arg
+do
+ delim=""
+ case "$arg" in
+ #translate --gnu-long-options to -g (short options)
+ --description) args="${args}-d ";;
+ --version) args="${args}-v ";;
+ --capabilities) args="${args}-c ";;
+ #pass through anything else
+ *) [[ "${arg:0:1}" == "-" ]] || delim="\""
+ args="${args}${delim}${arg}${delim} ";;
+ esac
+done
+
+#Reset the positional parameters to the short options
+eval set -- $args
+
+while getopts "dvc" option
+do
+ case $option in
+ d) dflag=1;;
+ v) vflag=1;;
+ c) cflag=1;;
+ \?) printf "unknown option: -%s\n" $OPTARG
+ printf "Usage: %s: [--description] [--version] [--capabilities] \n" $(basename $0)
+ exit 2
+ ;;
+ esac >&2
+done
+
+if [ "$dflag" ]
+then
+ printf "tv_grag_file is a simple grabber that just read the ~/.xmltv/tv_grab_file.xmltv file\n"
+fi
+if [ "$vflag" ]
+then
+ printf "0.1\n"
+fi
+if [ "$cflag" ]
+then
+ printf "baseline\n"
+fi
+
+exit 0
diff --git a/external/cache/sources/bananapi-config/softy b/external/cache/sources/bananapi-config/softy
new file mode 120000
index 0000000..c5bc43c
--- /dev/null
+++ b/external/cache/sources/bananapi-config/softy
@@ -0,0 +1 @@
+debian-software
\ No newline at end of file
diff --git a/external/cache/sources/brcm_patchram_plus/Makefile b/external/cache/sources/brcm_patchram_plus/Makefile
new file mode 100755
index 0000000..4cb8a93
--- /dev/null
+++ b/external/cache/sources/brcm_patchram_plus/Makefile
@@ -0,0 +1,20 @@
+# ----------------------------------------------------------------------------
+# Makefile for building tapp
+#
+#
+
+CFLAGS = -Wall -O2
+CC = gcc
+INSTALL = install
+
+TARGET = brcm_patchram_plus
+
+all: $(TARGET)
+
+$(TARGET): brcm_patchram_plus.c
+ $(CC) $(CFLAGS) $< -o $@
+clean distclean:
+ rm -rf *.o $(TARGET)
+# ----------------------------------------------------------------------------
+
+.PHONY: $(PHONY) install clean distclean
diff --git a/external/cache/sources/brcm_patchram_plus/brcm_patchram_plus.c b/external/cache/sources/brcm_patchram_plus/brcm_patchram_plus.c
new file mode 100755
index 0000000..e5fc6f1
--- /dev/null
+++ b/external/cache/sources/brcm_patchram_plus/brcm_patchram_plus.c
@@ -0,0 +1,890 @@
+/*******************************************************************************
+ *
+ * Copyright (C) 2009-2011 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/*****************************************************************************
+**
+** Name: brcm_patchram_plus.c
+**
+** Description: This program downloads a patchram files in the HCD format
+** to Broadcom Bluetooth based silicon and combo chips and
+** and other utility functions.
+**
+** It can be invoked from the command line in the form
+** <-d> to print a debug log
+** <--patchram patchram_file>
+** <--baudrate baud_rate>
+** <--bd_addr bd_address>
+** <--enable_lpm>
+** <--enable_hci>
+** <--use_baudrate_for_download>
+** <--scopcm=sco_routing,pcm_interface_rate,frame_type,
+** sync_mode,clock_mode,lsb_first,fill_bits,
+** fill_method,fill_num,right_justify>
+**
+** Where
+**
+** sco_routing is 0 for PCM, 1 for Transport,
+** 2 for Codec and 3 for I2S,
+**
+** pcm_interface_rate is 0 for 128KBps, 1 for
+** 256 KBps, 2 for 512KBps, 3 for 1024KBps,
+** and 4 for 2048Kbps,
+**
+** frame_type is 0 for short and 1 for long,
+**
+** sync_mode is 0 for slave and 1 for master,
+**
+** clock_mode is 0 for slabe and 1 for master,
+**
+** lsb_first is 0 for false aand 1 for true,
+**
+** fill_bits is the value in decimal for unused bits,
+**
+** fill_method is 0 for 0's and 1 for 1's, 2 for
+** signed and 3 for programmable,
+**
+** fill_num is the number or bits to fill,
+**
+** right_justify is 0 for false and 1 for true
+**
+** <--i2s=i2s_enable,is_master,sample_rate,clock_rate>
+**
+** Where
+**
+** i2s_enable is 0 for disable and 1 for enable,
+**
+** is_master is 0 for slave and 1 for master,
+**
+** sample_rate is 0 for 8KHz, 1 for 16Khz and
+** 2 for 4 KHz,
+**
+** clock_rate is 0 for 128KHz, 1 for 256KHz, 3 for
+** 1024 KHz and 4 for 2048 KHz.
+**
+** <--no2bytes skips waiting for two byte confirmation
+** before starting patchram download. Newer chips
+** do not generate these two bytes.>
+** <--tosleep=number of microsseconds to sleep before
+** patchram download begins.>
+** uart_device_name
+**
+** For example:
+**
+** brcm_patchram_plus -d --patchram \
+** BCM2045B2_002.002.011.0348.0349.hcd /dev/ttyHS0
+**
+** It will return 0 for success and a number greater than 0
+** for any errors.
+**
+** For Android, this program invoked using a
+** "system(2)" call from the beginning of the bt_enable
+** function inside the file
+** system/bluetooth/bluedroid/bluetooth.c.
+**
+** If the Android system property "ro.bt.bcm_bdaddr_path" is
+** set, then the bd_addr will be read from this path.
+** This is overridden by --bd_addr on the command line.
+**
+******************************************************************************/
+
+// TODO: Integrate BCM support into Bluez hciattach
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#ifdef ANDROID
+#include
+#else
+#include
+#include
+#include
+#endif
+
+#include
+#include
+
+#ifdef ANDROID
+#include
+#define LOG_TAG "brcm_patchram_plus"
+#include
+#undef printf
+#define printf ALOGD
+#undef fprintf
+#define fprintf(x, ...) \
+ { if(x==stderr) ALOGE(__VA_ARGS__); else fprintf(x, __VA_ARGS__); }
+
+#endif //ANDROID
+
+#ifndef N_HCI
+#define N_HCI 15
+#endif
+
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
+
+#define HCI_UART_H4 0
+#define HCI_UART_BCSP 1
+#define HCI_UART_3WIRE 2
+#define HCI_UART_H4DS 3
+#define HCI_UART_LL 4
+
+typedef unsigned char uchar;
+
+int uart_fd = -1;
+int hcdfile_fd = -1;
+int termios_baudrate = 0;
+int bdaddr_flag = 0;
+int enable_lpm = 0;
+int enable_hci = 0;
+int use_baudrate_for_download = 0;
+int debug = 0;
+int scopcm = 0;
+int i2s = 0;
+int no2bytes = 0;
+int tosleep = 0;
+
+struct termios termios;
+uchar buffer[1024];
+
+uchar hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
+
+uchar hci_download_minidriver[] = { 0x01, 0x2e, 0xfc, 0x00 };
+
+uchar hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_bd_addr[] = { 0x01, 0x01, 0xfc, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc, 0x0c,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00 };
+
+uchar hci_write_sco_pcm_int[] =
+ { 0x01, 0x1C, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_pcm_data_format[] =
+ { 0x01, 0x1e, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_i2spcm_interface_param[] =
+ { 0x01, 0x6d, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00 };
+
+#ifdef SAMSUNG_BLUETOOTH
+char* get_samsung_bluetooth_type()
+{
+ char buf[10];
+ int fd = open("/data/.cid.info", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "couldn't open file /data/.cid.info for reading\n");
+ return NULL;
+ }
+
+ if (read(fd, buf, sizeof(buf)) < 0) {
+ close(fd);
+ return NULL;
+ }
+
+ close(fd);
+
+ if (strncmp(buf, "murata", 6) == 0)
+ return "_murata";
+
+ if (strncmp(buf, "semcove", 7) == 0)
+ return "_semcove";
+
+ if (strncmp(buf, "semcosh", 7) == 0)
+ return "_semcosh";
+
+ return NULL;
+}
+#endif
+
+int
+parse_patchram(char *optarg)
+{
+ char *p;
+
+ if (!(p = strrchr(optarg, '.'))) {
+ fprintf(stderr, "file %s not an HCD file\n", optarg);
+ exit(3);
+ }
+
+ p++;
+
+ if (strcasecmp("hcd", p) != 0) {
+ fprintf(stderr, "file %s not an HCD file\n", optarg);
+ exit(4);
+ }
+
+#ifdef SAMSUNG_BLUETOOTH
+ char optarg2[256];
+ char* type = get_samsung_bluetooth_type();
+ char* fext = ".hcd";
+
+ if (type != NULL) {
+ memset(optarg2, 0, 256);
+ strncpy(optarg2, optarg, strlen(optarg) - 4);
+ strcpy(optarg2 + strlen(optarg2), type);
+ strcpy(optarg2 + strlen(optarg2), fext);
+ optarg = optarg2;
+ fprintf(stderr, "using %s as hcdfile\n", optarg);
+ }
+#endif
+
+ if ((hcdfile_fd = open(optarg, O_RDONLY)) == -1) {
+ fprintf(stderr, "file %s could not be opened, error %d\n", optarg, errno);
+ exit(5);
+ }
+
+ return(0);
+}
+
+void
+BRCM_encode_baud_rate(uint baud_rate, uchar *encoded_baud)
+{
+ if(baud_rate == 0 || encoded_baud == NULL) {
+ fprintf(stderr, "Baudrate not supported!");
+ return;
+ }
+
+ encoded_baud[3] = (uchar)(baud_rate >> 24);
+ encoded_baud[2] = (uchar)(baud_rate >> 16);
+ encoded_baud[1] = (uchar)(baud_rate >> 8);
+ encoded_baud[0] = (uchar)(baud_rate & 0xFF);
+}
+
+typedef struct {
+ int baud_rate;
+ int termios_value;
+} tBaudRates;
+
+tBaudRates baud_rates[] = {
+ { 115200, B115200 },
+ { 230400, B230400 },
+ { 460800, B460800 },
+ { 500000, B500000 },
+ { 576000, B576000 },
+ { 921600, B921600 },
+ { 1000000, B1000000 },
+ { 1152000, B1152000 },
+ { 1500000, B1500000 },
+ { 2000000, B2000000 },
+ { 2500000, B2500000 },
+ { 3000000, B3000000 },
+#ifndef __CYGWIN__
+ { 3500000, B3500000 },
+ { 4000000, B4000000 }
+#endif
+};
+
+int
+validate_baudrate(int baud_rate, int *value)
+{
+ unsigned int i;
+
+ for (i = 0; i < (sizeof(baud_rates) / sizeof(tBaudRates)); i++) {
+ if (baud_rates[i].baud_rate == baud_rate) {
+ *value = baud_rates[i].termios_value;
+ return(1);
+ }
+ }
+
+ return(0);
+}
+
+int
+parse_baudrate(char *optarg)
+{
+ int baudrate = atoi(optarg);
+
+ if (validate_baudrate(baudrate, &termios_baudrate)) {
+ BRCM_encode_baud_rate(baudrate, &hci_update_baud_rate[6]);
+ }
+
+ return(0);
+}
+
+int
+parse_bdaddr(char *optarg)
+{
+ int bd_addr[6];
+ int i;
+
+ sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X",
+ &bd_addr[5], &bd_addr[4], &bd_addr[3],
+ &bd_addr[2], &bd_addr[1], &bd_addr[0]);
+
+ for (i = 0; i < 6; i++) {
+ hci_write_bd_addr[4 + i] = bd_addr[i];
+ }
+
+ bdaddr_flag = 1;
+
+ return(0);
+}
+
+int
+parse_enable_lpm(char *optarg)
+{
+ enable_lpm = 1;
+ return(0);
+}
+
+int
+parse_use_baudrate_for_download(char *optarg)
+{
+ use_baudrate_for_download = 1;
+ return(0);
+}
+
+int
+parse_enable_hci(char *optarg)
+{
+ enable_hci = 1;
+ return(0);
+}
+
+int
+parse_scopcm(char *optarg)
+{
+ int param[10];
+ int ret;
+ int i;
+
+ ret = sscanf(optarg, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ ¶m[0], ¶m[1], ¶m[2], ¶m[3], ¶m[4],
+ ¶m[5], ¶m[6], ¶m[7], ¶m[8], ¶m[9]);
+
+ if (ret != 10) {
+ return(1);
+ }
+
+ scopcm = 1;
+
+ for (i = 0; i < 5; i++) {
+ hci_write_sco_pcm_int[4 + i] = param[i];
+ }
+
+ for (i = 0; i < 5; i++) {
+ hci_write_pcm_data_format[4 + i] = param[5 + i];
+ }
+
+ return(0);
+}
+
+int
+parse_i2s(char *optarg)
+{
+ int param[4];
+ int ret;
+ int i;
+
+ ret = sscanf(optarg, "%d,%d,%d,%d", ¶m[0], ¶m[1], ¶m[2],
+ ¶m[3]);
+
+ if (ret != 4) {
+ return(1);
+ }
+
+ i2s = 1;
+
+ for (i = 0; i < 4; i++) {
+ hci_write_i2spcm_interface_param[4 + i] = param[i];
+ }
+
+ return(0);
+}
+
+int
+parse_no2bytes(char *optarg)
+{
+ no2bytes = 1;
+ return(0);
+}
+
+int
+parse_tosleep(char *optarg)
+{
+ tosleep = atoi(optarg);
+
+ if (tosleep <= 0) {
+ return(1);
+ }
+
+ return(0);
+}
+
+void
+usage(char *argv0)
+{
+ printf("Usage %s:\n", argv0);
+ printf("\t<-d> to print a debug log\n");
+ printf("\t<--patchram patchram_file>\n");
+ printf("\t<--baudrate baud_rate>\n");
+ printf("\t<--bd_addr bd_address>\n");
+ printf("\t<--enable_lpm>\n");
+ printf("\t<--enable_hci>\n");
+ printf("\t<--use_baudrate_for_download> - Uses the\n");
+ printf("\t\tbaudrate for downloading the firmware\n");
+ printf("\t<--scopcm=sco_routing,pcm_interface_rate,frame_type,\n");
+ printf("\t\tsync_mode,clock_mode,lsb_first,fill_bits,\n");
+ printf("\t\tfill_method,fill_num,right_justify>\n");
+ printf("\n\t\tWhere\n");
+ printf("\n\t\tsco_routing is 0 for PCM, 1 for Transport,\n");
+ printf("\t\t2 for Codec and 3 for I2S,\n");
+ printf("\n\t\tpcm_interface_rate is 0 for 128KBps, 1 for\n");
+ printf("\t\t256 KBps, 2 for 512KBps, 3 for 1024KBps,\n");
+ printf("\t\tand 4 for 2048Kbps,\n");
+ printf("\n\t\tframe_type is 0 for short and 1 for long,\n");
+ printf("\t\tsync_mode is 0 for slave and 1 for master,\n");
+ printf("\n\t\tclock_mode is 0 for slabe and 1 for master,\n");
+ printf("\n\t\tlsb_first is 0 for false aand 1 for true,\n");
+ printf("\n\t\tfill_bits is the value in decimal for unused bits,\n");
+ printf("\n\t\tfill_method is 0 for 0's and 1 for 1's, 2 for\n");
+ printf("\t\tsigned and 3 for programmable,\n");
+ printf("\n\t\tfill_num is the number or bits to fill,\n");
+ printf("\n\t\tright_justify is 0 for false and 1 for true\n");
+ printf("\n\t<--i2s=i2s_enable,is_master,sample_rate,clock_rate>\n");
+ printf("\n\t\tWhere\n");
+ printf("\n\t\ti2s_enable is 0 for disable and 1 for enable,\n");
+ printf("\n\t\tis_master is 0 for slave and 1 for master,\n");
+ printf("\n\t\tsample_rate is 0 for 8KHz, 1 for 16Khz and\n");
+ printf("\t\t2 for 4 KHz,\n");
+ printf("\n\t\tclock_rate is 0 for 128KHz, 1 for 256KHz, 3 for\n");
+ printf("\t\t1024 KHz and 4 for 2048 KHz.\n\n");
+ printf("\t<--no2bytes skips waiting for two byte confirmation\n");
+ printf("\t\tbefore starting patchram download. Newer chips\n");
+ printf("\t\tdo not generate these two bytes.>\n");
+ printf("\t<--tosleep=microseconds>\n");
+ printf("\tuart_device_name\n");
+}
+
+int
+parse_cmd_line(int argc, char **argv)
+{
+ int c;
+ int ret = 0;
+
+ typedef int (*PFI)();
+
+ PFI parse[] = { parse_patchram, parse_baudrate,
+ parse_bdaddr, parse_enable_lpm, parse_enable_hci,
+ parse_use_baudrate_for_download,
+ parse_scopcm, parse_i2s, parse_no2bytes, parse_tosleep};
+
+ while (1) {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+
+ static struct option long_options[] = {
+ {"patchram", 1, 0, 0},
+ {"baudrate", 1, 0, 0},
+ {"bd_addr", 1, 0, 0},
+ {"enable_lpm", 0, 0, 0},
+ {"enable_hci", 0, 0, 0},
+ {"use_baudrate_for_download", 0, 0, 0},
+ {"scopcm", 1, 0, 0},
+ {"i2s", 1, 0, 0},
+ {"no2bytes", 0, 0, 0},
+ {"tosleep", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long_only (argc, argv, "d", long_options,
+ &option_index);
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 0:
+ if (debug) {
+ printf ("option %s",
+ long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ }
+
+ ret = (*parse[option_index])(optarg);
+
+ break;
+ case 'd':
+ debug = 1;
+ break;
+
+ case '?':
+ //nobreak
+ default:
+ usage(argv[0]);
+ break;
+ }
+
+ if (ret) {
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if (ret) {
+ return(1);
+ }
+
+ if (optind < argc) {
+ if (debug)
+ printf ("%s \n", argv[optind]);
+ if ((uart_fd = open(argv[optind], O_RDWR | O_NOCTTY)) == -1) {
+ fprintf(stderr, "port %s could not be opened, error %d\n",
+ argv[optind], errno);
+ }
+ }
+
+ return(0);
+}
+
+void
+init_uart()
+{
+#ifdef BCM_INIT_DELAY
+ usleep(150*1000);
+#endif
+ tcflush(uart_fd, TCIOFLUSH);
+ tcgetattr(uart_fd, &termios);
+
+#ifndef __CYGWIN__
+ cfmakeraw(&termios);
+#else
+ termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+ | INLCR | IGNCR | ICRNL | IXON);
+ termios.c_oflag &= ~OPOST;
+ termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ termios.c_cflag &= ~(CSIZE | PARENB);
+ termios.c_cflag |= CS8;
+#endif
+
+ termios.c_cflag |= CRTSCTS;
+ tcsetattr(uart_fd, TCSANOW, &termios);
+ tcflush(uart_fd, TCIOFLUSH);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+ tcflush(uart_fd, TCIOFLUSH);
+ tcflush(uart_fd, TCIOFLUSH);
+ cfsetospeed(&termios, B115200);
+ cfsetispeed(&termios, B115200);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+}
+
+void
+dump(uchar *out, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (i && !(i % 16)) {
+ fprintf(stderr, "\n");
+ }
+
+ fprintf(stderr, "%02x ", out[i]);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void
+read_event(int fd, uchar *buffer)
+{
+ int i = 0;
+ int len = 3;
+ int count;
+
+ while ((count = read(fd, &buffer[i], len)) < len) {
+ i += count;
+ len -= count;
+ }
+
+ i += count;
+ len = buffer[2];
+
+ while ((count = read(fd, &buffer[i], len)) < len) {
+ i += count;
+ len -= count;
+ }
+
+ if (debug) {
+ count += i;
+
+ fprintf(stderr, "received %d\n", count);
+ dump(buffer, count);
+ }
+}
+
+void
+hci_send_cmd(uchar *buf, int len)
+{
+ if (debug) {
+ fprintf(stderr, "writing\n");
+ dump(buf, len);
+ }
+
+ write(uart_fd, buf, len);
+}
+
+void
+expired(int sig)
+{
+ hci_send_cmd(hci_reset, sizeof(hci_reset));
+ alarm(4);
+}
+
+void
+proc_reset()
+{
+ signal(SIGALRM, expired);
+
+
+ hci_send_cmd(hci_reset, sizeof(hci_reset));
+
+ alarm(4);
+
+ read_event(uart_fd, buffer);
+
+ alarm(0);
+}
+
+void
+proc_patchram()
+{
+ int len;
+
+ hci_send_cmd(hci_download_minidriver, sizeof(hci_download_minidriver));
+
+ read_event(uart_fd, buffer);
+
+ if (!no2bytes) {
+ read(uart_fd, &buffer[0], 2);
+ }
+
+ if (tosleep) {
+ usleep(tosleep);
+ }
+
+ while (read(hcdfile_fd, &buffer[1], 3)) {
+ buffer[0] = 0x01;
+
+ len = buffer[3];
+
+ read(hcdfile_fd, &buffer[4], len);
+
+ hci_send_cmd(buffer, len + 4);
+
+ read_event(uart_fd, buffer);
+ }
+
+ if (use_baudrate_for_download) {
+ cfsetospeed(&termios, B115200);
+ cfsetispeed(&termios, B115200);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+ }
+ proc_reset();
+}
+
+void
+proc_baudrate()
+{
+ hci_send_cmd(hci_update_baud_rate, sizeof(hci_update_baud_rate));
+
+ read_event(uart_fd, buffer);
+
+ cfsetospeed(&termios, termios_baudrate);
+ cfsetispeed(&termios, termios_baudrate);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+
+ if (debug) {
+ fprintf(stderr, "Done setting baudrate\n");
+ }
+}
+
+void
+proc_bdaddr()
+{
+ hci_send_cmd(hci_write_bd_addr, sizeof(hci_write_bd_addr));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_enable_lpm()
+{
+ hci_send_cmd(hci_write_sleep_mode, sizeof(hci_write_sleep_mode));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_scopcm()
+{
+ hci_send_cmd(hci_write_sco_pcm_int,
+ sizeof(hci_write_sco_pcm_int));
+
+ read_event(uart_fd, buffer);
+
+ hci_send_cmd(hci_write_pcm_data_format,
+ sizeof(hci_write_pcm_data_format));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_i2s()
+{
+ hci_send_cmd(hci_write_i2spcm_interface_param,
+ sizeof(hci_write_i2spcm_interface_param));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_enable_hci()
+{
+ int i = N_HCI;
+ int proto = HCI_UART_H4;
+ if (ioctl(uart_fd, TIOCSETD, &i) < 0) {
+ fprintf(stderr, "Can't set line discipline\n");
+ return;
+ }
+
+ if (ioctl(uart_fd, HCIUARTSETPROTO, proto) < 0) {
+ fprintf(stderr, "Can't set hci protocol\n");
+ return;
+ }
+ fprintf(stderr, "Done setting line discpline\n");
+ return;
+}
+
+#ifdef ANDROID
+void
+read_default_bdaddr()
+{
+ int sz;
+ int fd;
+
+ char path[PROPERTY_VALUE_MAX];
+
+ char bdaddr[18];
+ int len = 17;
+ memset(bdaddr, 0, (len + 1) * sizeof(char));
+
+ property_get("ro.bt.bdaddr_path", path, "");
+ if (path[0] == 0)
+ return;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "open(%s) failed: %s (%d)", path, strerror(errno),
+ errno);
+ return;
+ }
+
+ sz = read(fd, bdaddr, len);
+ if (sz < 0) {
+ fprintf(stderr, "read(%s) failed: %s (%d)", path, strerror(errno),
+ errno);
+ close(fd);
+ return;
+ } else if (sz != len) {
+ fprintf(stderr, "read(%s) unexpected size %d", path, sz);
+ close(fd);
+ return;
+ }
+
+ if (debug) {
+ printf("Read default bdaddr of %s\n", bdaddr);
+ }
+
+ parse_bdaddr(bdaddr);
+}
+#endif
+
+
+int
+main (int argc, char **argv)
+{
+#ifdef ANDROID
+ read_default_bdaddr();
+#endif
+
+ if (parse_cmd_line(argc, argv)) {
+ exit(1);
+ }
+
+ if (uart_fd < 0) {
+ exit(2);
+ }
+
+ init_uart();
+
+ proc_reset();
+
+ if (use_baudrate_for_download) {
+ if (termios_baudrate) {
+ proc_baudrate();
+ }
+ }
+
+ if (hcdfile_fd > 0) {
+ proc_patchram();
+ }
+
+ if (termios_baudrate) {
+ proc_baudrate();
+ }
+
+ if (bdaddr_flag) {
+ proc_bdaddr();
+ }
+
+ if (enable_lpm) {
+ proc_enable_lpm();
+ }
+
+ if (scopcm) {
+ proc_scopcm();
+ }
+
+ if (i2s) {
+ proc_i2s();
+ }
+
+ if (enable_hci) {
+ proc_enable_hci();
+
+ while (1) {
+ sleep(UINT_MAX);
+ }
+ }
+
+ exit(0);
+}
diff --git a/external/cache/sources/hcitools/Makefile b/external/cache/sources/hcitools/Makefile
new file mode 100644
index 0000000..d902df9
--- /dev/null
+++ b/external/cache/sources/hcitools/Makefile
@@ -0,0 +1,95 @@
+#CFLAGS := $(CFLAGS) -g
+CFLAGS = -I. -Ilib -Wall -DVERSION=\"5.10\" -Wno-strict-aliasing
+CFLAGS += -Ilib/bluetooth
+
+# include rule.mk
+include ./rule.mk
+
+# define objects collection variable
+lib = \
+ lib/bluetooth.o \
+ lib/hci.o \
+ lib/sdp.o
+
+hciattach_objs = \
+ hciattach.o \
+ hciattach_ath3k.o \
+ hciattach_bcm43xx.o \
+ hciattach_intel.o \
+ hciattach_qualcomm.o \
+ hciattach_st.o \
+ hciattach_ti.o \
+ hciattach_tialt.o \
+ hciattach_rtk.o \
+ hciattach_xr.o \
+ hciattach_sprd.o
+
+hciconfig_objs = \
+ hciconfig.o \
+ csr.o
+
+hcitool_objs = \
+ hcitool.o
+
+btmon_objs = \
+ monitor/main.o \
+ monitor/mainloop.o \
+ monitor/display.o \
+ monitor/hcidump.o \
+ monitor/btsnoop.o \
+ monitor/control.o \
+ monitor/packet.o \
+ monitor/vendor.o \
+ monitor/lmp.o \
+ monitor/l2cap.o \
+ monitor/uuid.o \
+ monitor/sdp.o \
+ monitor/crc.o \
+ monitor/ll.o
+
+# add your target(s) to all
+.PHONY: all
+all: hciattach_opi hciconfig hcitool btmon
+
+# directory
+hciattach_opi: $(hciattach_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+hciconfig: $(hciconfig_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+hcitool: $(hcitool_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+btmon: $(btmon_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+# change objs to your objects collection variable
+$(hciattach_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+$(hciconfig_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+$(hcitool_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+$(btmon_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+# clean temp files
+clean:
+ -rm -rf $(hciattach_objs) $(hciattach_objs:.o=.d)
+ -rm -rf $(hciconfig_objs) $(hciconfig_objs:.o=.d)
+ -rm -rf $(hcitool_objs) $(hcitool_objs:.o=.d)
+ -rm -rf $(lib) $(lib:.o=.d)
+ -rm -rf $(btmon_objs) $(btmon_objs:.o=.d)
+ #-rm -rf output
diff --git a/external/cache/sources/hcitools/NOTICE b/external/cache/sources/hcitools/NOTICE
new file mode 100644
index 0000000..52321cc
--- /dev/null
+++ b/external/cache/sources/hcitools/NOTICE
@@ -0,0 +1,343 @@
+All of these programs are made available under version 2 of the GNU General
+Public Licence.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/external/cache/sources/hcitools/csr.c b/external/cache/sources/hcitools/csr.c
new file mode 100644
index 0000000..b4ea1fb
--- /dev/null
+++ b/external/cache/sources/hcitools/csr.c
@@ -0,0 +1,2853 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "csr.h"
+
+struct psr_data {
+ uint16_t pskey;
+ uint8_t *value;
+ uint8_t size;
+ struct psr_data *next;
+};
+
+static struct psr_data *head = NULL, *tail = NULL;
+
+static struct {
+ uint16_t id;
+ char *str;
+} csr_map[] = {
+ { 66, "HCI 9.8" },
+ { 97, "HCI 10.3" },
+ { 101, "HCI 10.5" },
+ { 111, "HCI 11.0" },
+ { 112, "HCI 11.1" },
+ { 114, "HCI 11.2" },
+ { 115, "HCI 11.3" },
+ { 117, "HCI 12.0" },
+ { 119, "HCI 12.1" },
+ { 133, "HCI 12.2" },
+ { 134, "HCI 12.3" },
+ { 162, "HCI 12.4" },
+ { 165, "HCI 12.5" },
+ { 169, "HCI 12.6" },
+ { 188, "HCI 12.7" },
+ { 218, "HCI 12.8" },
+ { 283, "HCI 12.9" },
+ { 203, "HCI 13.2" },
+ { 204, "HCI 13.2" },
+ { 210, "HCI 13.3" },
+ { 211, "HCI 13.3" },
+ { 213, "HCI 13.4" },
+ { 214, "HCI 13.4" },
+ { 225, "HCI 13.5" },
+ { 226, "HCI 13.5" },
+ { 237, "HCI 13.6" },
+ { 238, "HCI 13.6" },
+ { 242, "HCI 14.0" },
+ { 243, "HCI 14.0" },
+ { 244, "HCI 14.0" },
+ { 245, "HCI 14.0" },
+ { 254, "HCI 13.7" },
+ { 255, "HCI 13.7" },
+ { 264, "HCI 14.1" },
+ { 265, "HCI 14.1" },
+ { 267, "HCI 14.2" },
+ { 268, "HCI 14.2" },
+ { 272, "HCI 14.3" },
+ { 273, "HCI 14.3" },
+ { 274, "HCI 13.8" },
+ { 275, "HCI 13.8" },
+ { 286, "HCI 13.9" },
+ { 287, "HCI 13.9" },
+ { 309, "HCI 13.10" },
+ { 310, "HCI 13.10" },
+ { 313, "HCI 14.4" },
+ { 314, "HCI 14.4" },
+ { 323, "HCI 14.5" },
+ { 324, "HCI 14.5" },
+ { 336, "HCI 14.6" },
+ { 337, "HCI 14.6" },
+ { 351, "HCI 13.11" },
+ { 352, "HCI 13.11" },
+ { 362, "HCI 15.0" },
+ { 363, "HCI 15.0" },
+ { 364, "HCI 15.0" },
+ { 365, "HCI 15.0" },
+ { 373, "HCI 14.7" },
+ { 374, "HCI 14.7" },
+ { 379, "HCI 15.1" },
+ { 380, "HCI 15.1" },
+ { 381, "HCI 15.1" },
+ { 382, "HCI 15.1" },
+ { 392, "HCI 15.2" },
+ { 393, "HCI 15.2" },
+ { 394, "HCI 15.2" },
+ { 395, "HCI 15.2" },
+ { 436, "HCI 16.0" },
+ { 437, "HCI 16.0" },
+ { 438, "HCI 16.0" },
+ { 439, "HCI 16.0" },
+ { 443, "HCI 15.3" },
+ { 444, "HCI 15.3" },
+ { 465, "HCI 16.1" },
+ { 466, "HCI 16.1" },
+ { 467, "HCI 16.1" },
+ { 468, "HCI 16.1" },
+ { 487, "HCI 14.8" },
+ { 488, "HCI 14.8" },
+ { 492, "HCI 16.2" },
+ { 493, "HCI 16.2" },
+ { 495, "HCI 16.2" },
+ { 496, "HCI 16.2" },
+ { 502, "HCI 16.1.1" },
+ { 503, "HCI 16.1.1" },
+ { 504, "HCI 16.1.1" },
+ { 505, "HCI 16.1.1" },
+ { 506, "HCI 16.1.2" },
+ { 507, "HCI 16.1.2" },
+ { 508, "HCI 16.1.2" },
+ { 509, "HCI 16.1.2" },
+ { 516, "HCI 16.3" },
+ { 517, "HCI 16.3" },
+ { 518, "HCI 16.3" },
+ { 519, "HCI 16.3" },
+ { 523, "HCI 16.4" },
+ { 524, "HCI 16.4" },
+ { 525, "HCI 16.4" },
+ { 526, "HCI 16.4" },
+ { 553, "HCI 15.3" },
+ { 554, "HCI 15.3" },
+ { 562, "HCI 16.5" },
+ { 563, "HCI 16.5" },
+ { 564, "HCI 16.5" },
+ { 565, "HCI 16.5" },
+ { 593, "HCI 17.0" },
+ { 594, "HCI 17.0" },
+ { 595, "HCI 17.0" },
+ { 599, "HCI 17.0" },
+ { 600, "HCI 17.0" },
+ { 608, "HCI 13.10.1" },
+ { 609, "HCI 13.10.1" },
+ { 613, "HCI 17.1" },
+ { 614, "HCI 17.1" },
+ { 615, "HCI 17.1" },
+ { 616, "HCI 17.1" },
+ { 618, "HCI 17.1" },
+ { 624, "HCI 17.2" },
+ { 625, "HCI 17.2" },
+ { 626, "HCI 17.2" },
+ { 627, "HCI 17.2" },
+ { 637, "HCI 16.6" },
+ { 638, "HCI 16.6" },
+ { 639, "HCI 16.6" },
+ { 640, "HCI 16.6" },
+ { 642, "HCI 13.10.2" },
+ { 643, "HCI 13.10.2" },
+ { 644, "HCI 13.10.3" },
+ { 645, "HCI 13.10.3" },
+ { 668, "HCI 13.10.4" },
+ { 669, "HCI 13.10.4" },
+ { 681, "HCI 16.7" },
+ { 682, "HCI 16.7" },
+ { 683, "HCI 16.7" },
+ { 684, "HCI 16.7" },
+ { 704, "HCI 16.8" },
+ { 718, "HCI 16.4.1" },
+ { 719, "HCI 16.4.1" },
+ { 720, "HCI 16.4.1" },
+ { 721, "HCI 16.4.1" },
+ { 722, "HCI 16.7.1" },
+ { 723, "HCI 16.7.1" },
+ { 724, "HCI 16.7.1" },
+ { 725, "HCI 16.7.1" },
+ { 731, "HCI 16.7.2" },
+ { 732, "HCI 16.7.2" },
+ { 733, "HCI 16.7.2" },
+ { 734, "HCI 16.7.2" },
+ { 735, "HCI 16.4.2" },
+ { 736, "HCI 16.4.2" },
+ { 737, "HCI 16.4.2" },
+ { 738, "HCI 16.4.2" },
+ { 750, "HCI 16.7.3" },
+ { 751, "HCI 16.7.3" },
+ { 752, "HCI 16.7.3" },
+ { 753, "HCI 16.7.3" },
+ { 760, "HCI 16.7.4" },
+ { 761, "HCI 16.7.4" },
+ { 762, "HCI 16.7.4" },
+ { 763, "HCI 16.7.4" },
+ { 770, "HCI 16.9" },
+ { 771, "HCI 16.9" },
+ { 772, "HCI 16.9" },
+ { 773, "HCI 16.9" },
+ { 774, "HCI 17.3" },
+ { 775, "HCI 17.3" },
+ { 776, "HCI 17.3" },
+ { 777, "HCI 17.3" },
+ { 781, "HCI 16.7.5" },
+ { 786, "HCI 16.10" },
+ { 787, "HCI 16.10" },
+ { 788, "HCI 16.10" },
+ { 789, "HCI 16.10" },
+ { 791, "HCI 16.4.3" },
+ { 792, "HCI 16.4.3" },
+ { 793, "HCI 16.4.3" },
+ { 794, "HCI 16.4.3" },
+ { 798, "HCI 16.11" },
+ { 799, "HCI 16.11" },
+ { 800, "HCI 16.11" },
+ { 801, "HCI 16.11" },
+ { 806, "HCI 16.7.5" },
+ { 807, "HCI 16.12" },
+ { 808, "HCI 16.12" },
+ { 809, "HCI 16.12" },
+ { 810, "HCI 16.12" },
+ { 817, "HCI 16.13" },
+ { 818, "HCI 16.13" },
+ { 819, "HCI 16.13" },
+ { 820, "HCI 16.13" },
+ { 823, "HCI 13.10.5" },
+ { 824, "HCI 13.10.5" },
+ { 826, "HCI 16.14" },
+ { 827, "HCI 16.14" },
+ { 828, "HCI 16.14" },
+ { 829, "HCI 16.14" },
+ { 843, "HCI 17.3.1" },
+ { 856, "HCI 17.3.2" },
+ { 857, "HCI 17.3.2" },
+ { 858, "HCI 17.3.2" },
+ { 1120, "HCI 17.11" },
+ { 1168, "HCI 18.1" },
+ { 1169, "HCI 18.1" },
+ { 1241, "HCI 18.x" },
+ { 1298, "HCI 18.2" },
+ { 1354, "HCI 18.2" },
+ { 1392, "HCI 18.2" },
+ { 1393, "HCI 18.2" },
+ { 1501, "HCI 18.2" },
+ { 1503, "HCI 18.2" },
+ { 1504, "HCI 18.2" },
+ { 1505, "HCI 18.2" },
+ { 1506, "HCI 18.2" },
+ { 1520, "HCI 18.2" },
+ { 1586, "HCI 18.2" },
+ { 1591, "HCI 18.2" },
+ { 1592, "HCI 18.2" },
+ { 1593, "HCI 18.2.1" },
+ { 1733, "HCI 18.3" },
+ { 1734, "HCI 18.3" },
+ { 1735, "HCI 18.3" },
+ { 1737, "HCI 18.3" },
+ { 1915, "HCI 19.2" },
+ { 1916, "HCI 19.2" },
+ { 1958, "HCI 19.2" },
+ { 1981, "Unified 20a" },
+ { 1982, "Unified 20a" },
+ { 1989, "HCI 18.4" },
+ { 2062, "Unified 20a1" },
+ { 2063, "Unified 20a1" },
+ { 2067, "Unified 18f" },
+ { 2068, "Unified 18f" },
+ { 2243, "Unified 18e" },
+ { 2244, "Unified 18e" },
+ { 2258, "Unified 20d" },
+ { 2259, "Unified 20d" },
+ { 2361, "Unified 20e" },
+ { 2362, "Unified 20e" },
+ { 2386, "Unified 21a" },
+ { 2387, "Unified 21a" },
+ { 2423, "Unified 21a" },
+ { 2424, "Unified 21a" },
+ { 2623, "Unified 21c" },
+ { 2624, "Unified 21c" },
+ { 2625, "Unified 21c" },
+ { 2626, "Unified 21c" },
+ { 2627, "Unified 21c" },
+ { 2628, "Unified 21c" },
+ { 2629, "Unified 21c" },
+ { 2630, "Unified 21c" },
+ { 2631, "Unified 21c" },
+ { 2632, "Unified 21c" },
+ { 2633, "Unified 21c" },
+ { 2634, "Unified 21c" },
+ { 2635, "Unified 21c" },
+ { 2636, "Unified 21c" },
+ { 2649, "Unified 21c" },
+ { 2650, "Unified 21c" },
+ { 2651, "Unified 21c" },
+ { 2652, "Unified 21c" },
+ { 2653, "Unified 21c" },
+ { 2654, "Unified 21c" },
+ { 2655, "Unified 21c" },
+ { 2656, "Unified 21c" },
+ { 2658, "Unified 21c" },
+ { 3057, "Unified 21d" },
+ { 3058, "Unified 21d" },
+ { 3059, "Unified 21d" },
+ { 3060, "Unified 21d" },
+ { 3062, "Unified 21d" },
+ { 3063, "Unified 21d" },
+ { 3064, "Unified 21d" },
+ { 3164, "Unified 21e" },
+ { 3413, "Unified 21f" },
+ { 3414, "Unified 21f" },
+ { 3415, "Unified 21f" },
+ { 3424, "Unified 21f" },
+ { 3454, "Unified 21f" },
+ { 3684, "Unified 21f" },
+ { 3764, "Unified 21f" },
+ { 4276, "Unified 22b" },
+ { 4277, "Unified 22b" },
+ { 4279, "Unified 22b" },
+ { 4281, "Unified 22b" },
+ { 4282, "Unified 22b" },
+ { 4283, "Unified 22b" },
+ { 4284, "Unified 22b" },
+ { 4285, "Unified 22b" },
+ { 4289, "Unified 22b" },
+ { 4290, "Unified 22b" },
+ { 4291, "Unified 22b" },
+ { 4292, "Unified 22b" },
+ { 4293, "Unified 22b" },
+ { 4294, "Unified 22b" },
+ { 4295, "Unified 22b" },
+ { 4363, "Unified 22c" },
+ { 4373, "Unified 22c" },
+ { 4374, "Unified 22c" },
+ { 4532, "Unified 22d" },
+ { 4533, "Unified 22d" },
+ { 4698, "Unified 23c" },
+ { 4839, "Unified 23c" },
+ { 4841, "Unified 23c" },
+ { 4866, "Unified 23c" },
+ { 4867, "Unified 23c" },
+ { 4868, "Unified 23c" },
+ { 4869, "Unified 23c" },
+ { 4870, "Unified 23c" },
+ { 4871, "Unified 23c" },
+ { 4872, "Unified 23c" },
+ { 4874, "Unified 23c" },
+ { 4875, "Unified 23c" },
+ { 4876, "Unified 23c" },
+ { 4877, "Unified 23c" },
+ { 2526, "Marcel 1 (2005-09-26)" },
+ { 2543, "Marcel 2 (2005-09-28)" },
+ { 2622, "Marcel 3 (2005-10-27)" },
+ { 3326, "Marcel 4 (2006-06-16)" },
+ { 3612, "Marcel 5 (2006-10-24)" },
+ { 4509, "Marcel 6 (2007-06-11)" },
+ { 5417, "Marcel 7 (2008-08-26)" },
+ { 195, "Sniff 1 (2001-11-27)" },
+ { 220, "Sniff 2 (2002-01-03)" },
+ { 269, "Sniff 3 (2002-02-22)" },
+ { 270, "Sniff 4 (2002-02-26)" },
+ { 284, "Sniff 5 (2002-03-12)" },
+ { 292, "Sniff 6 (2002-03-20)" },
+ { 305, "Sniff 7 (2002-04-12)" },
+ { 306, "Sniff 8 (2002-04-12)" },
+ { 343, "Sniff 9 (2002-05-02)" },
+ { 346, "Sniff 10 (2002-05-03)" },
+ { 355, "Sniff 11 (2002-05-16)" },
+ { 256, "Sniff 11 (2002-05-16)" },
+ { 390, "Sniff 12 (2002-06-26)" },
+ { 450, "Sniff 13 (2002-08-16)" },
+ { 451, "Sniff 13 (2002-08-16)" },
+ { 533, "Sniff 14 (2002-10-11)" },
+ { 580, "Sniff 15 (2002-11-14)" },
+ { 623, "Sniff 16 (2002-12-12)" },
+ { 678, "Sniff 17 (2003-01-29)" },
+ { 847, "Sniff 18 (2003-04-17)" },
+ { 876, "Sniff 19 (2003-06-10)" },
+ { 997, "Sniff 22 (2003-09-05)" },
+ { 1027, "Sniff 23 (2003-10-03)" },
+ { 1029, "Sniff 24 (2003-10-03)" },
+ { 1112, "Sniff 25 (2003-12-03)" },
+ { 1113, "Sniff 25 (2003-12-03)" },
+ { 1133, "Sniff 26 (2003-12-18)" },
+ { 1134, "Sniff 26 (2003-12-18)" },
+ { 1223, "Sniff 27 (2004-03-08)" },
+ { 1224, "Sniff 27 (2004-03-08)" },
+ { 1319, "Sniff 31 (2004-04-22)" },
+ { 1320, "Sniff 31 (2004-04-22)" },
+ { 1427, "Sniff 34 (2004-06-16)" },
+ { 1508, "Sniff 35 (2004-07-19)" },
+ { 1509, "Sniff 35 (2004-07-19)" },
+ { 1587, "Sniff 36 (2004-08-18)" },
+ { 1588, "Sniff 36 (2004-08-18)" },
+ { 1641, "Sniff 37 (2004-09-16)" },
+ { 1642, "Sniff 37 (2004-09-16)" },
+ { 1699, "Sniff 38 (2004-10-07)" },
+ { 1700, "Sniff 38 (2004-10-07)" },
+ { 1752, "Sniff 39 (2004-11-02)" },
+ { 1753, "Sniff 39 (2004-11-02)" },
+ { 1759, "Sniff 40 (2004-11-03)" },
+ { 1760, "Sniff 40 (2004-11-03)" },
+ { 1761, "Sniff 40 (2004-11-03)" },
+ { 2009, "Sniff 41 (2005-04-06)" },
+ { 2010, "Sniff 41 (2005-04-06)" },
+ { 2011, "Sniff 41 (2005-04-06)" },
+ { 2016, "Sniff 42 (2005-04-11)" },
+ { 2017, "Sniff 42 (2005-04-11)" },
+ { 2018, "Sniff 42 (2005-04-11)" },
+ { 2023, "Sniff 43 (2005-04-14)" },
+ { 2024, "Sniff 43 (2005-04-14)" },
+ { 2025, "Sniff 43 (2005-04-14)" },
+ { 2032, "Sniff 44 (2005-04-18)" },
+ { 2033, "Sniff 44 (2005-04-18)" },
+ { 2034, "Sniff 44 (2005-04-18)" },
+ { 2288, "Sniff 45 (2005-07-08)" },
+ { 2289, "Sniff 45 (2005-07-08)" },
+ { 2290, "Sniff 45 (2005-07-08)" },
+ { 2388, "Sniff 46 (2005-08-17)" },
+ { 2389, "Sniff 46 (2005-08-17)" },
+ { 2390, "Sniff 46 (2005-08-17)" },
+ { 2869, "Sniff 47 (2006-02-15)" },
+ { 2870, "Sniff 47 (2006-02-15)" },
+ { 2871, "Sniff 47 (2006-02-15)" },
+ { 3214, "Sniff 48 (2006-05-16)" },
+ { 3215, "Sniff 48 (2006-05-16)" },
+ { 3216, "Sniff 48 (2006-05-16)" },
+ { 3356, "Sniff 49 (2006-07-17)" },
+ { 3529, "Sniff 50 (2006-09-21)" },
+ { 3546, "Sniff 51 (2006-09-29)" },
+ { 3683, "Sniff 52 (2006-11-03)" },
+ { 0, }
+};
+
+char *csr_builddeftostr(uint16_t def)
+{
+ switch (def) {
+ case 0x0000:
+ return "NONE";
+ case 0x0001:
+ return "CHIP_BASE_BC01";
+ case 0x0002:
+ return "CHIP_BASE_BC02";
+ case 0x0003:
+ return "CHIP_BC01B";
+ case 0x0004:
+ return "CHIP_BC02_EXTERNAL";
+ case 0x0005:
+ return "BUILD_HCI";
+ case 0x0006:
+ return "BUILD_RFCOMM";
+ case 0x0007:
+ return "BT_VER_1_1";
+ case 0x0008:
+ return "TRANSPORT_ALL";
+ case 0x0009:
+ return "TRANSPORT_BCSP";
+ case 0x000a:
+ return "TRANSPORT_H4";
+ case 0x000b:
+ return "TRANSPORT_USB";
+ case 0x000c:
+ return "MAX_CRYPT_KEY_LEN_56";
+ case 0x000d:
+ return "MAX_CRYPT_KEY_LEN_128";
+ case 0x000e:
+ return "TRANSPORT_USER";
+ case 0x000f:
+ return "CHIP_BC02_KATO";
+ case 0x0010:
+ return "TRANSPORT_NONE";
+ case 0x0012:
+ return "REQUIRE_8MBIT";
+ case 0x0013:
+ return "RADIOTEST";
+ case 0x0014:
+ return "RADIOTEST_LITE";
+ case 0x0015:
+ return "INSTALL_FLASH";
+ case 0x0016:
+ return "INSTALL_EEPROM";
+ case 0x0017:
+ return "INSTALL_COMBO_DOT11";
+ case 0x0018:
+ return "LOWPOWER_TX";
+ case 0x0019:
+ return "TRANSPORT_TWUTL";
+ case 0x001a:
+ return "COMPILER_GCC";
+ case 0x001b:
+ return "CHIP_BC02_CLOUSEAU";
+ case 0x001c:
+ return "CHIP_BC02_TOULOUSE";
+ case 0x001d:
+ return "CHIP_BASE_BC3";
+ case 0x001e:
+ return "CHIP_BC3_NICKNACK";
+ case 0x001f:
+ return "CHIP_BC3_KALIMBA";
+ case 0x0020:
+ return "INSTALL_HCI_MODULE";
+ case 0x0021:
+ return "INSTALL_L2CAP_MODULE";
+ case 0x0022:
+ return "INSTALL_DM_MODULE";
+ case 0x0023:
+ return "INSTALL_SDP_MODULE";
+ case 0x0024:
+ return "INSTALL_RFCOMM_MODULE";
+ case 0x0025:
+ return "INSTALL_HIDIO_MODULE";
+ case 0x0026:
+ return "INSTALL_PAN_MODULE";
+ case 0x0027:
+ return "INSTALL_IPV4_MODULE";
+ case 0x0028:
+ return "INSTALL_IPV6_MODULE";
+ case 0x0029:
+ return "INSTALL_TCP_MODULE";
+ case 0x002a:
+ return "BT_VER_1_2";
+ case 0x002b:
+ return "INSTALL_UDP_MODULE";
+ case 0x002c:
+ return "REQUIRE_0_WAIT_STATES";
+ case 0x002d:
+ return "CHIP_BC3_PADDYWACK";
+ case 0x002e:
+ return "CHIP_BC4_COYOTE";
+ case 0x002f:
+ return "CHIP_BC4_ODDJOB";
+ case 0x0030:
+ return "TRANSPORT_H4DS";
+ case 0x0031:
+ return "CHIP_BASE_BC4";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+char *csr_buildidtostr(uint16_t id)
+{
+ static char str[12];
+ int i;
+
+ for (i = 0; csr_map[i].id; i++)
+ if (csr_map[i].id == id)
+ return csr_map[i].str;
+
+ snprintf(str, 11, "Build %d", id);
+ return str;
+}
+
+char *csr_chipvertostr(uint16_t ver, uint16_t rev)
+{
+ switch (ver) {
+ case 0x00:
+ return "BlueCore01a";
+ case 0x01:
+ switch (rev) {
+ case 0x64:
+ return "BlueCore01b (ES)";
+ case 0x65:
+ default:
+ return "BlueCore01b";
+ }
+ case 0x02:
+ switch (rev) {
+ case 0x89:
+ return "BlueCore02-External (ES2)";
+ case 0x8a:
+ return "BlueCore02-External";
+ case 0x28:
+ return "BlueCore02-ROM/Audio/Flash";
+ default:
+ return "BlueCore02";
+ }
+ case 0x03:
+ switch (rev) {
+ case 0x43:
+ return "BlueCore3-MM";
+ case 0x15:
+ return "BlueCore3-ROM";
+ case 0xe2:
+ return "BlueCore3-Flash";
+ case 0x26:
+ return "BlueCore4-External";
+ case 0x30:
+ return "BlueCore4-ROM";
+ default:
+ return "BlueCore3 or BlueCore4";
+ }
+ default:
+ return "Unknown";
+ }
+}
+
+char *csr_pskeytostr(uint16_t pskey)
+{
+ switch (pskey) {
+ case CSR_PSKEY_BDADDR:
+ return "Bluetooth address";
+ case CSR_PSKEY_COUNTRYCODE:
+ return "Country code";
+ case CSR_PSKEY_CLASSOFDEVICE:
+ return "Class of device";
+ case CSR_PSKEY_DEVICE_DRIFT:
+ return "Device drift";
+ case CSR_PSKEY_DEVICE_JITTER:
+ return "Device jitter";
+ case CSR_PSKEY_MAX_ACLS:
+ return "Maximum ACL links";
+ case CSR_PSKEY_MAX_SCOS:
+ return "Maximum SCO links";
+ case CSR_PSKEY_MAX_REMOTE_MASTERS:
+ return "Maximum remote masters";
+ case CSR_PSKEY_ENABLE_MASTERY_WITH_SLAVERY:
+ return "Support master and slave roles simultaneously";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKT_LEN:
+ return "Maximum HCI ACL packet length";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKT_LEN:
+ return "Maximum HCI SCO packet length";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKTS:
+ return "Maximum number of HCI ACL packets";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKTS:
+ return "Maximum number of HCI SCO packets";
+ case CSR_PSKEY_LC_FC_BUFFER_LOW_WATER_MARK:
+ return "Flow control low water mark";
+ case CSR_PSKEY_LC_MAX_TX_POWER:
+ return "Maximum transmit power";
+ case CSR_PSKEY_TX_GAIN_RAMP:
+ return "Transmit gain ramp rate";
+ case CSR_PSKEY_LC_POWER_TABLE:
+ return "Radio power table";
+ case CSR_PSKEY_LC_PEER_POWER_PERIOD:
+ return "Peer transmit power control interval";
+ case CSR_PSKEY_LC_FC_POOLS_LOW_WATER_MARK:
+ return "Flow control pool low water mark";
+ case CSR_PSKEY_LC_DEFAULT_TX_POWER:
+ return "Default transmit power";
+ case CSR_PSKEY_LC_RSSI_GOLDEN_RANGE:
+ return "RSSI at bottom of golden receive range";
+ case CSR_PSKEY_LC_COMBO_DISABLE_PIO_MASK:
+ return "Combo: PIO lines and logic to disable transmit";
+ case CSR_PSKEY_LC_COMBO_PRIORITY_PIO_MASK:
+ return "Combo: priority activity PIO lines and logic";
+ case CSR_PSKEY_LC_COMBO_DOT11_CHANNEL_PIO_BASE:
+ return "Combo: 802.11b channel number base PIO line";
+ case CSR_PSKEY_LC_COMBO_DOT11_BLOCK_CHANNELS:
+ return "Combo: channels to block either side of 802.11b";
+ case CSR_PSKEY_LC_MAX_TX_POWER_NO_RSSI:
+ return "Maximum transmit power when peer has no RSSI";
+ case CSR_PSKEY_LC_CONNECTION_RX_WINDOW:
+ return "Receive window size during connections";
+ case CSR_PSKEY_LC_COMBO_DOT11_TX_PROTECTION_MODE:
+ return "Combo: which TX packets shall we protect";
+ case CSR_PSKEY_LC_ENHANCED_POWER_TABLE:
+ return "Radio power table";
+ case CSR_PSKEY_LC_WIDEBAND_RSSI_CONFIG:
+ return "RSSI configuration for use with wideband RSSI";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_LEAD:
+ return "Combo: How much notice will we give the Combo Card";
+ case CSR_PSKEY_BT_CLOCK_INIT:
+ return "Initial value of Bluetooth clock";
+ case CSR_PSKEY_TX_MR_MOD_DELAY:
+ return "TX Mod delay";
+ case CSR_PSKEY_RX_MR_SYNC_TIMING:
+ return "RX MR Sync Timing";
+ case CSR_PSKEY_RX_MR_SYNC_CONFIG:
+ return "RX MR Sync Configuration";
+ case CSR_PSKEY_LC_LOST_SYNC_SLOTS:
+ return "Time in ms for lost sync in low power modes";
+ case CSR_PSKEY_RX_MR_SAMP_CONFIG:
+ return "RX MR Sync Configuration";
+ case CSR_PSKEY_AGC_HYST_LEVELS:
+ return "AGC hysteresis levels";
+ case CSR_PSKEY_RX_LEVEL_LOW_SIGNAL:
+ return "ANA_RX_LVL at low signal strengths";
+ case CSR_PSKEY_AGC_IQ_LVL_VALUES:
+ return "ANA_IQ_LVL values for AGC algorithmn";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_12DB:
+ return "ANA_RX_FTRIM offset when using 12 dB IF atten ";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_6DB:
+ return "ANA_RX_FTRIM offset when using 6 dB IF atten ";
+ case CSR_PSKEY_NO_CAL_ON_BOOT:
+ return "Do not calibrate radio on boot";
+ case CSR_PSKEY_RSSI_HI_TARGET:
+ return "RSSI high target";
+ case CSR_PSKEY_PREFERRED_MIN_ATTENUATION:
+ return "Preferred minimum attenuator setting";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_OVERRIDE:
+ return "Combo: Treat all packets as high priority";
+ case CSR_PSKEY_LC_MULTISLOT_HOLDOFF:
+ return "Time till single slot packets are used for resync";
+ case CSR_PSKEY_FREE_KEY_PIGEON_HOLE:
+ return "Link key store bitfield";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR0:
+ return "Bluetooth address + link key 0";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR1:
+ return "Bluetooth address + link key 1";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR2:
+ return "Bluetooth address + link key 2";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR3:
+ return "Bluetooth address + link key 3";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR4:
+ return "Bluetooth address + link key 4";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR5:
+ return "Bluetooth address + link key 5";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR6:
+ return "Bluetooth address + link key 6";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR7:
+ return "Bluetooth address + link key 7";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR8:
+ return "Bluetooth address + link key 8";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR9:
+ return "Bluetooth address + link key 9";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR10:
+ return "Bluetooth address + link key 10";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR11:
+ return "Bluetooth address + link key 11";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR12:
+ return "Bluetooth address + link key 12";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR13:
+ return "Bluetooth address + link key 13";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR14:
+ return "Bluetooth address + link key 14";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR15:
+ return "Bluetooth address + link key 15";
+ case CSR_PSKEY_ENC_KEY_LMIN:
+ return "Minimum encryption key length";
+ case CSR_PSKEY_ENC_KEY_LMAX:
+ return "Maximum encryption key length";
+ case CSR_PSKEY_LOCAL_SUPPORTED_FEATURES:
+ return "Local supported features block";
+ case CSR_PSKEY_LM_USE_UNIT_KEY:
+ return "Allow use of unit key for authentication?";
+ case CSR_PSKEY_HCI_NOP_DISABLE:
+ return "Disable the HCI Command_Status event on boot";
+ case CSR_PSKEY_LM_MAX_EVENT_FILTERS:
+ return "Maximum number of event filters";
+ case CSR_PSKEY_LM_USE_ENC_MODE_BROADCAST:
+ return "Allow LM to use enc_mode=2";
+ case CSR_PSKEY_LM_TEST_SEND_ACCEPTED_TWICE:
+ return "LM sends two LMP_accepted messages in test mode";
+ case CSR_PSKEY_LM_MAX_PAGE_HOLD_TIME:
+ return "Maximum time we hold a device around page";
+ case CSR_PSKEY_AFH_ADAPTATION_RESPONSE_TIME:
+ return "LM period for AFH adaption";
+ case CSR_PSKEY_AFH_OPTIONS:
+ return "Options to configure AFH";
+ case CSR_PSKEY_AFH_RSSI_RUN_PERIOD:
+ return "AFH RSSI reading period";
+ case CSR_PSKEY_AFH_REENABLE_CHANNEL_TIME:
+ return "AFH good channel adding time";
+ case CSR_PSKEY_NO_DROP_ON_ACR_MS_FAIL:
+ return "Complete link if acr barge-in role switch refused";
+ case CSR_PSKEY_MAX_PRIVATE_KEYS:
+ return "Max private link keys stored";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR0:
+ return "Bluetooth address + link key 0";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR1:
+ return "Bluetooth address + link key 1";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR2:
+ return "Bluetooth address + link key 2";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR3:
+ return "Bluetooth address + link key 3";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR4:
+ return "Bluetooth address + link key 4";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR5:
+ return "Bluetooth address + link key 5";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR6:
+ return "Bluetooth address + link key 6";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR7:
+ return "Bluetooth address + link key 7";
+ case CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS:
+ return "Local supported commands";
+ case CSR_PSKEY_LM_MAX_ABSENCE_INDEX:
+ return "Maximum absence index allowed";
+ case CSR_PSKEY_DEVICE_NAME:
+ return "Local device's \"user friendly\" name";
+ case CSR_PSKEY_AFH_RSSI_THRESHOLD:
+ return "AFH RSSI threshold";
+ case CSR_PSKEY_LM_CASUAL_SCAN_INTERVAL:
+ return "Scan interval in slots for casual scanning";
+ case CSR_PSKEY_AFH_MIN_MAP_CHANGE:
+ return "The minimum amount to change an AFH map by";
+ case CSR_PSKEY_AFH_RSSI_LP_RUN_PERIOD:
+ return "AFH RSSI reading period when in low power mode";
+ case CSR_PSKEY_HCI_LMP_LOCAL_VERSION:
+ return "The HCI and LMP version reported locally";
+ case CSR_PSKEY_LMP_REMOTE_VERSION:
+ return "The LMP version reported remotely";
+ case CSR_PSKEY_HOLD_ERROR_MESSAGE_NUMBER:
+ return "Maximum number of queued HCI Hardware Error Events";
+ case CSR_PSKEY_DFU_ATTRIBUTES:
+ return "DFU attributes";
+ case CSR_PSKEY_DFU_DETACH_TO:
+ return "DFU detach timeout";
+ case CSR_PSKEY_DFU_TRANSFER_SIZE:
+ return "DFU transfer size";
+ case CSR_PSKEY_DFU_ENABLE:
+ return "DFU enable";
+ case CSR_PSKEY_DFU_LIN_REG_ENABLE:
+ return "Linear Regulator enabled at boot in DFU mode";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_MSB:
+ return "DFU encryption VM application public key MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_LSB:
+ return "DFU encryption VM application public key LSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_M_DASH:
+ return "DFU encryption VM application M dash";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_MSB:
+ return "DFU encryption VM application public key R2N MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_LSB:
+ return "DFU encryption VM application public key R2N LSB";
+ case CSR_PSKEY_BCSP_LM_PS_BLOCK:
+ return "BCSP link establishment block";
+ case CSR_PSKEY_HOSTIO_FC_PS_BLOCK:
+ return "HCI flow control block";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO0:
+ return "Host transport channel 0 settings (BCSP ACK)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO1:
+ return "Host transport channel 1 settings (BCSP-LE)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO2:
+ return "Host transport channel 2 settings (BCCMD)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO3:
+ return "Host transport channel 3 settings (HQ)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO4:
+ return "Host transport channel 4 settings (DM)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO5:
+ return "Host transport channel 5 settings (HCI CMD/EVT)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO6:
+ return "Host transport channel 6 settings (HCI ACL)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO7:
+ return "Host transport channel 7 settings (HCI SCO)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO8:
+ return "Host transport channel 8 settings (L2CAP)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO9:
+ return "Host transport channel 9 settings (RFCOMM)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO10:
+ return "Host transport channel 10 settings (SDP)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO11:
+ return "Host transport channel 11 settings (TEST)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO12:
+ return "Host transport channel 12 settings (DFU)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO13:
+ return "Host transport channel 13 settings (VM)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO14:
+ return "Host transport channel 14 settings";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO15:
+ return "Host transport channel 15 settings";
+ case CSR_PSKEY_HOSTIO_UART_RESET_TIMEOUT:
+ return "UART reset counter timeout";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN:
+ return "Use hci_extn to route non-hci channels";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN_CCFC:
+ return "Use command-complete flow control for hci_extn";
+ case CSR_PSKEY_HOSTIO_HCI_EXTN_PAYLOAD_SIZE:
+ return "Maximum hci_extn payload size";
+ case CSR_PSKEY_BCSP_LM_CNF_CNT_LIMIT:
+ return "BCSP link establishment conf message count";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM:
+ return "Map SCO over PCM";
+ case CSR_PSKEY_HOSTIO_AWKWARD_PCM_SYNC:
+ return "PCM interface synchronisation is difficult";
+ case CSR_PSKEY_HOSTIO_BREAK_POLL_PERIOD:
+ return "Break poll period (microseconds)";
+ case CSR_PSKEY_HOSTIO_MIN_UART_HCI_SCO_SIZE:
+ return "Minimum SCO packet size sent to host over UART HCI";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_CODEC:
+ return "Map SCO over the built-in codec";
+ case CSR_PSKEY_PCM_CVSD_TX_HI_FREQ_BOOST:
+ return "High frequency boost for PCM when transmitting CVSD";
+ case CSR_PSKEY_PCM_CVSD_RX_HI_FREQ_BOOST:
+ return "High frequency boost for PCM when receiving CVSD";
+ case CSR_PSKEY_PCM_CONFIG32:
+ return "PCM interface settings bitfields";
+ case CSR_PSKEY_USE_OLD_BCSP_LE:
+ return "Use the old version of BCSP link establishment";
+ case CSR_PSKEY_PCM_CVSD_USE_NEW_FILTER:
+ return "CVSD uses the new filter if available";
+ case CSR_PSKEY_PCM_FORMAT:
+ return "PCM data format";
+ case CSR_PSKEY_CODEC_OUT_GAIN:
+ return "Audio output gain when using built-in codec";
+ case CSR_PSKEY_CODEC_IN_GAIN:
+ return "Audio input gain when using built-in codec";
+ case CSR_PSKEY_CODEC_PIO:
+ return "PIO to enable when built-in codec is enabled";
+ case CSR_PSKEY_PCM_LOW_JITTER_CONFIG:
+ return "PCM interface settings for low jitter master mode";
+ case CSR_PSKEY_HOSTIO_SCO_PCM_THRESHOLDS:
+ return "Thresholds for SCO PCM buffers";
+ case CSR_PSKEY_HOSTIO_SCO_HCI_THRESHOLDS:
+ return "Thresholds for SCO HCI buffers";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM_SLOT:
+ return "Route SCO data to specified slot in pcm frame";
+ case CSR_PSKEY_UART_BAUDRATE:
+ return "UART Baud rate";
+ case CSR_PSKEY_UART_CONFIG_BCSP:
+ return "UART configuration when using BCSP";
+ case CSR_PSKEY_UART_CONFIG_H4:
+ return "UART configuration when using H4";
+ case CSR_PSKEY_UART_CONFIG_H5:
+ return "UART configuration when using H5";
+ case CSR_PSKEY_UART_CONFIG_USR:
+ return "UART configuration when under VM control";
+ case CSR_PSKEY_UART_TX_CRCS:
+ return "Use CRCs for BCSP or H5";
+ case CSR_PSKEY_UART_ACK_TIMEOUT:
+ return "Acknowledgement timeout for BCSP and H5";
+ case CSR_PSKEY_UART_TX_MAX_ATTEMPTS:
+ return "Max times to send reliable BCSP or H5 message";
+ case CSR_PSKEY_UART_TX_WINDOW_SIZE:
+ return "Transmit window size for BCSP and H5";
+ case CSR_PSKEY_UART_HOST_WAKE:
+ return "UART host wakeup";
+ case CSR_PSKEY_HOSTIO_THROTTLE_TIMEOUT:
+ return "Host interface performance control.";
+ case CSR_PSKEY_PCM_ALWAYS_ENABLE:
+ return "PCM port is always enable when chip is running";
+ case CSR_PSKEY_UART_HOST_WAKE_SIGNAL:
+ return "Signal to use for uart host wakeup protocol";
+ case CSR_PSKEY_UART_CONFIG_H4DS:
+ return "UART configuration when using H4DS";
+ case CSR_PSKEY_H4DS_WAKE_DURATION:
+ return "How long to spend waking the host when using H4DS";
+ case CSR_PSKEY_H4DS_MAXWU:
+ return "Maximum number of H4DS Wake-Up messages to send";
+ case CSR_PSKEY_H4DS_LE_TIMER_PERIOD:
+ return "H4DS Link Establishment Tsync and Tconf period";
+ case CSR_PSKEY_H4DS_TWU_TIMER_PERIOD:
+ return "H4DS Twu timer period";
+ case CSR_PSKEY_H4DS_UART_IDLE_TIMER_PERIOD:
+ return "H4DS Tuart_idle timer period";
+ case CSR_PSKEY_ANA_FTRIM:
+ return "Crystal frequency trim";
+ case CSR_PSKEY_WD_TIMEOUT:
+ return "Watchdog timeout (microseconds)";
+ case CSR_PSKEY_WD_PERIOD:
+ return "Watchdog period (microseconds)";
+ case CSR_PSKEY_HOST_INTERFACE:
+ return "Host interface";
+ case CSR_PSKEY_HQ_HOST_TIMEOUT:
+ return "HQ host command timeout";
+ case CSR_PSKEY_HQ_ACTIVE:
+ return "Enable host query task?";
+ case CSR_PSKEY_BCCMD_SECURITY_ACTIVE:
+ return "Enable configuration security";
+ case CSR_PSKEY_ANA_FREQ:
+ return "Crystal frequency";
+ case CSR_PSKEY_PIO_PROTECT_MASK:
+ return "Access to PIO pins";
+ case CSR_PSKEY_PMALLOC_SIZES:
+ return "pmalloc sizes array";
+ case CSR_PSKEY_UART_BAUD_RATE:
+ return "UART Baud rate (pre 18)";
+ case CSR_PSKEY_UART_CONFIG:
+ return "UART configuration bitfield";
+ case CSR_PSKEY_STUB:
+ return "Stub";
+ case CSR_PSKEY_TXRX_PIO_CONTROL:
+ return "TX and RX PIO control";
+ case CSR_PSKEY_ANA_RX_LEVEL:
+ return "ANA_RX_LVL register initial value";
+ case CSR_PSKEY_ANA_RX_FTRIM:
+ return "ANA_RX_FTRIM register initial value";
+ case CSR_PSKEY_PSBC_DATA_VERSION:
+ return "Persistent store version";
+ case CSR_PSKEY_PCM0_ATTENUATION:
+ return "Volume control on PCM channel 0";
+ case CSR_PSKEY_LO_LVL_MAX:
+ return "Maximum value of LO level control register";
+ case CSR_PSKEY_LO_ADC_AMPL_MIN:
+ return "Minimum value of the LO amplitude measured on the ADC";
+ case CSR_PSKEY_LO_ADC_AMPL_MAX:
+ return "Maximum value of the LO amplitude measured on the ADC";
+ case CSR_PSKEY_IQ_TRIM_CHANNEL:
+ return "IQ calibration channel";
+ case CSR_PSKEY_IQ_TRIM_GAIN:
+ return "IQ calibration gain";
+ case CSR_PSKEY_IQ_TRIM_ENABLE:
+ return "IQ calibration enable";
+ case CSR_PSKEY_TX_OFFSET_HALF_MHZ:
+ return "Transmit offset";
+ case CSR_PSKEY_GBL_MISC_ENABLES:
+ return "Global miscellaneous hardware enables";
+ case CSR_PSKEY_UART_SLEEP_TIMEOUT:
+ return "Time in ms to deep sleep if nothing received";
+ case CSR_PSKEY_DEEP_SLEEP_STATE:
+ return "Deep sleep state usage";
+ case CSR_PSKEY_IQ_ENABLE_PHASE_TRIM:
+ return "IQ phase enable";
+ case CSR_PSKEY_HCI_HANDLE_FREEZE_PERIOD:
+ return "Time for which HCI handle is frozen after link removal";
+ case CSR_PSKEY_MAX_FROZEN_HCI_HANDLES:
+ return "Maximum number of frozen HCI handles";
+ case CSR_PSKEY_PAGETABLE_DESTRUCTION_DELAY:
+ return "Delay from freezing buf handle to deleting page table";
+ case CSR_PSKEY_IQ_TRIM_PIO_SETTINGS:
+ return "IQ PIO settings";
+ case CSR_PSKEY_USE_EXTERNAL_CLOCK:
+ return "Device uses an external clock";
+ case CSR_PSKEY_DEEP_SLEEP_WAKE_CTS:
+ return "Exit deep sleep on CTS line activity";
+ case CSR_PSKEY_FC_HC2H_FLUSH_DELAY:
+ return "Delay from disconnect to flushing HC->H FC tokens";
+ case CSR_PSKEY_RX_HIGHSIDE:
+ return "Disable the HIGHSIDE bit in ANA_CONFIG";
+ case CSR_PSKEY_TX_PRE_LVL:
+ return "TX pre-amplifier level";
+ case CSR_PSKEY_RX_SINGLE_ENDED:
+ return "RX single ended";
+ case CSR_PSKEY_TX_FILTER_CONFIG:
+ return "TX filter configuration";
+ case CSR_PSKEY_CLOCK_REQUEST_ENABLE:
+ return "External clock request enable";
+ case CSR_PSKEY_RX_MIN_ATTEN:
+ return "Minimum attenuation allowed for receiver";
+ case CSR_PSKEY_XTAL_TARGET_AMPLITUDE:
+ return "Crystal target amplitude";
+ case CSR_PSKEY_PCM_MIN_CPU_CLOCK:
+ return "Minimum CPU clock speed with PCM port running";
+ case CSR_PSKEY_HOST_INTERFACE_PIO_USB:
+ return "USB host interface selection PIO line";
+ case CSR_PSKEY_CPU_IDLE_MODE:
+ return "CPU idle mode when radio is active";
+ case CSR_PSKEY_DEEP_SLEEP_CLEAR_RTS:
+ return "Deep sleep clears the UART RTS line";
+ case CSR_PSKEY_RF_RESONANCE_TRIM:
+ return "Frequency trim for IQ and LNA resonant circuits";
+ case CSR_PSKEY_DEEP_SLEEP_PIO_WAKE:
+ return "PIO line to wake the chip from deep sleep";
+ case CSR_PSKEY_DRAIN_BORE_TIMERS:
+ return "Energy consumption measurement settings";
+ case CSR_PSKEY_DRAIN_TX_POWER_BASE:
+ return "Energy consumption measurement settings";
+ case CSR_PSKEY_MODULE_ID:
+ return "Module serial number";
+ case CSR_PSKEY_MODULE_DESIGN:
+ return "Module design ID";
+ case CSR_PSKEY_MODULE_SECURITY_CODE:
+ return "Module security code";
+ case CSR_PSKEY_VM_DISABLE:
+ return "VM disable";
+ case CSR_PSKEY_MOD_MANUF0:
+ return "Module manufactuer data 0";
+ case CSR_PSKEY_MOD_MANUF1:
+ return "Module manufactuer data 1";
+ case CSR_PSKEY_MOD_MANUF2:
+ return "Module manufactuer data 2";
+ case CSR_PSKEY_MOD_MANUF3:
+ return "Module manufactuer data 3";
+ case CSR_PSKEY_MOD_MANUF4:
+ return "Module manufactuer data 4";
+ case CSR_PSKEY_MOD_MANUF5:
+ return "Module manufactuer data 5";
+ case CSR_PSKEY_MOD_MANUF6:
+ return "Module manufactuer data 6";
+ case CSR_PSKEY_MOD_MANUF7:
+ return "Module manufactuer data 7";
+ case CSR_PSKEY_MOD_MANUF8:
+ return "Module manufactuer data 8";
+ case CSR_PSKEY_MOD_MANUF9:
+ return "Module manufactuer data 9";
+ case CSR_PSKEY_DUT_VM_DISABLE:
+ return "VM disable when entering radiotest modes";
+ case CSR_PSKEY_USR0:
+ return "User configuration data 0";
+ case CSR_PSKEY_USR1:
+ return "User configuration data 1";
+ case CSR_PSKEY_USR2:
+ return "User configuration data 2";
+ case CSR_PSKEY_USR3:
+ return "User configuration data 3";
+ case CSR_PSKEY_USR4:
+ return "User configuration data 4";
+ case CSR_PSKEY_USR5:
+ return "User configuration data 5";
+ case CSR_PSKEY_USR6:
+ return "User configuration data 6";
+ case CSR_PSKEY_USR7:
+ return "User configuration data 7";
+ case CSR_PSKEY_USR8:
+ return "User configuration data 8";
+ case CSR_PSKEY_USR9:
+ return "User configuration data 9";
+ case CSR_PSKEY_USR10:
+ return "User configuration data 10";
+ case CSR_PSKEY_USR11:
+ return "User configuration data 11";
+ case CSR_PSKEY_USR12:
+ return "User configuration data 12";
+ case CSR_PSKEY_USR13:
+ return "User configuration data 13";
+ case CSR_PSKEY_USR14:
+ return "User configuration data 14";
+ case CSR_PSKEY_USR15:
+ return "User configuration data 15";
+ case CSR_PSKEY_USR16:
+ return "User configuration data 16";
+ case CSR_PSKEY_USR17:
+ return "User configuration data 17";
+ case CSR_PSKEY_USR18:
+ return "User configuration data 18";
+ case CSR_PSKEY_USR19:
+ return "User configuration data 19";
+ case CSR_PSKEY_USR20:
+ return "User configuration data 20";
+ case CSR_PSKEY_USR21:
+ return "User configuration data 21";
+ case CSR_PSKEY_USR22:
+ return "User configuration data 22";
+ case CSR_PSKEY_USR23:
+ return "User configuration data 23";
+ case CSR_PSKEY_USR24:
+ return "User configuration data 24";
+ case CSR_PSKEY_USR25:
+ return "User configuration data 25";
+ case CSR_PSKEY_USR26:
+ return "User configuration data 26";
+ case CSR_PSKEY_USR27:
+ return "User configuration data 27";
+ case CSR_PSKEY_USR28:
+ return "User configuration data 28";
+ case CSR_PSKEY_USR29:
+ return "User configuration data 29";
+ case CSR_PSKEY_USR30:
+ return "User configuration data 30";
+ case CSR_PSKEY_USR31:
+ return "User configuration data 31";
+ case CSR_PSKEY_USR32:
+ return "User configuration data 32";
+ case CSR_PSKEY_USR33:
+ return "User configuration data 33";
+ case CSR_PSKEY_USR34:
+ return "User configuration data 34";
+ case CSR_PSKEY_USR35:
+ return "User configuration data 35";
+ case CSR_PSKEY_USR36:
+ return "User configuration data 36";
+ case CSR_PSKEY_USR37:
+ return "User configuration data 37";
+ case CSR_PSKEY_USR38:
+ return "User configuration data 38";
+ case CSR_PSKEY_USR39:
+ return "User configuration data 39";
+ case CSR_PSKEY_USR40:
+ return "User configuration data 40";
+ case CSR_PSKEY_USR41:
+ return "User configuration data 41";
+ case CSR_PSKEY_USR42:
+ return "User configuration data 42";
+ case CSR_PSKEY_USR43:
+ return "User configuration data 43";
+ case CSR_PSKEY_USR44:
+ return "User configuration data 44";
+ case CSR_PSKEY_USR45:
+ return "User configuration data 45";
+ case CSR_PSKEY_USR46:
+ return "User configuration data 46";
+ case CSR_PSKEY_USR47:
+ return "User configuration data 47";
+ case CSR_PSKEY_USR48:
+ return "User configuration data 48";
+ case CSR_PSKEY_USR49:
+ return "User configuration data 49";
+ case CSR_PSKEY_USB_VERSION:
+ return "USB specification version number";
+ case CSR_PSKEY_USB_DEVICE_CLASS_CODES:
+ return "USB device class codes";
+ case CSR_PSKEY_USB_VENDOR_ID:
+ return "USB vendor identifier";
+ case CSR_PSKEY_USB_PRODUCT_ID:
+ return "USB product identifier";
+ case CSR_PSKEY_USB_MANUF_STRING:
+ return "USB manufacturer string";
+ case CSR_PSKEY_USB_PRODUCT_STRING:
+ return "USB product string";
+ case CSR_PSKEY_USB_SERIAL_NUMBER_STRING:
+ return "USB serial number string";
+ case CSR_PSKEY_USB_CONFIG_STRING:
+ return "USB configuration string";
+ case CSR_PSKEY_USB_ATTRIBUTES:
+ return "USB attributes bitmap";
+ case CSR_PSKEY_USB_MAX_POWER:
+ return "USB device maximum power consumption";
+ case CSR_PSKEY_USB_BT_IF_CLASS_CODES:
+ return "USB Bluetooth interface class codes";
+ case CSR_PSKEY_USB_LANGID:
+ return "USB language strings supported";
+ case CSR_PSKEY_USB_DFU_CLASS_CODES:
+ return "USB DFU class codes block";
+ case CSR_PSKEY_USB_DFU_PRODUCT_ID:
+ return "USB DFU product ID";
+ case CSR_PSKEY_USB_PIO_DETACH:
+ return "USB detach/attach PIO line";
+ case CSR_PSKEY_USB_PIO_WAKEUP:
+ return "USB wakeup PIO line";
+ case CSR_PSKEY_USB_PIO_PULLUP:
+ return "USB D+ pullup PIO line";
+ case CSR_PSKEY_USB_PIO_VBUS:
+ return "USB VBus detection PIO Line";
+ case CSR_PSKEY_USB_PIO_WAKE_TIMEOUT:
+ return "Timeout for assertion of USB PIO wake signal";
+ case CSR_PSKEY_USB_PIO_RESUME:
+ return "PIO signal used in place of bus resume";
+ case CSR_PSKEY_USB_BT_SCO_IF_CLASS_CODES:
+ return "USB Bluetooth SCO interface class codes";
+ case CSR_PSKEY_USB_SUSPEND_PIO_LEVEL:
+ return "USB PIO levels to set when suspended";
+ case CSR_PSKEY_USB_SUSPEND_PIO_DIR:
+ return "USB PIO I/O directions to set when suspended";
+ case CSR_PSKEY_USB_SUSPEND_PIO_MASK:
+ return "USB PIO lines to be set forcibly in suspend";
+ case CSR_PSKEY_USB_ENDPOINT_0_MAX_PACKET_SIZE:
+ return "The maxmimum packet size for USB endpoint 0";
+ case CSR_PSKEY_USB_CONFIG:
+ return "USB config params for new chips (>bc2)";
+ case CSR_PSKEY_RADIOTEST_ATTEN_INIT:
+ return "Radio test initial attenuator";
+ case CSR_PSKEY_RADIOTEST_FIRST_TRIM_TIME:
+ return "IQ first calibration period in test";
+ case CSR_PSKEY_RADIOTEST_SUBSEQUENT_TRIM_TIME:
+ return "IQ subsequent calibration period in test";
+ case CSR_PSKEY_RADIOTEST_LO_LVL_TRIM_ENABLE:
+ return "LO_LVL calibration enable";
+ case CSR_PSKEY_RADIOTEST_DISABLE_MODULATION:
+ return "Disable modulation during radiotest transmissions";
+ case CSR_PSKEY_RFCOMM_FCON_THRESHOLD:
+ return "RFCOMM aggregate flow control on threshold";
+ case CSR_PSKEY_RFCOMM_FCOFF_THRESHOLD:
+ return "RFCOMM aggregate flow control off threshold";
+ case CSR_PSKEY_IPV6_STATIC_ADDR:
+ return "Static IPv6 address";
+ case CSR_PSKEY_IPV4_STATIC_ADDR:
+ return "Static IPv4 address";
+ case CSR_PSKEY_IPV6_STATIC_PREFIX_LEN:
+ return "Static IPv6 prefix length";
+ case CSR_PSKEY_IPV6_STATIC_ROUTER_ADDR:
+ return "Static IPv6 router address";
+ case CSR_PSKEY_IPV4_STATIC_SUBNET_MASK:
+ return "Static IPv4 subnet mask";
+ case CSR_PSKEY_IPV4_STATIC_ROUTER_ADDR:
+ return "Static IPv4 router address";
+ case CSR_PSKEY_MDNS_NAME:
+ return "Multicast DNS name";
+ case CSR_PSKEY_FIXED_PIN:
+ return "Fixed PIN";
+ case CSR_PSKEY_MDNS_PORT:
+ return "Multicast DNS port";
+ case CSR_PSKEY_MDNS_TTL:
+ return "Multicast DNS TTL";
+ case CSR_PSKEY_MDNS_IPV4_ADDR:
+ return "Multicast DNS IPv4 address";
+ case CSR_PSKEY_ARP_CACHE_TIMEOUT:
+ return "ARP cache timeout";
+ case CSR_PSKEY_HFP_POWER_TABLE:
+ return "HFP power table";
+ case CSR_PSKEY_DRAIN_BORE_TIMER_COUNTERS:
+ return "Energy consumption estimation timer counters";
+ case CSR_PSKEY_DRAIN_BORE_COUNTERS:
+ return "Energy consumption estimation counters";
+ case CSR_PSKEY_LOOP_FILTER_TRIM:
+ return "Trim value to optimise loop filter";
+ case CSR_PSKEY_DRAIN_BORE_CURRENT_PEAK:
+ return "Energy consumption estimation current peak";
+ case CSR_PSKEY_VM_E2_CACHE_LIMIT:
+ return "Maximum RAM for caching EEPROM VM application";
+ case CSR_PSKEY_FORCE_16MHZ_REF_PIO:
+ return "PIO line to force 16 MHz reference to be assumed";
+ case CSR_PSKEY_CDMA_LO_REF_LIMITS:
+ return "Local oscillator frequency reference limits for CDMA";
+ case CSR_PSKEY_CDMA_LO_ERROR_LIMITS:
+ return "Local oscillator frequency error limits for CDMA";
+ case CSR_PSKEY_CLOCK_STARTUP_DELAY:
+ return "Clock startup delay in milliseconds";
+ case CSR_PSKEY_DEEP_SLEEP_CORRECTION_FACTOR:
+ return "Deep sleep clock correction factor";
+ case CSR_PSKEY_TEMPERATURE_CALIBRATION:
+ return "Temperature in deg C for a given internal setting";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA:
+ return "Temperature for given internal PA adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL:
+ return "Temperature for a given TX_PRE_LVL adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB:
+ return "Temperature for a given TX_BB adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_ANA_FTRIM:
+ return "Temperature for given crystal trim adjustment";
+ case CSR_PSKEY_TEST_DELTA_OFFSET:
+ return "Frequency offset applied to synthesiser in test mode";
+ case CSR_PSKEY_RX_DYNAMIC_LVL_OFFSET:
+ return "Receiver dynamic level offset depending on channel";
+ case CSR_PSKEY_TEST_FORCE_OFFSET:
+ return "Force use of exact value in PSKEY_TEST_DELTA_OFFSET";
+ case CSR_PSKEY_RF_TRAP_BAD_DIVISION_RATIOS:
+ return "Trap bad division ratios in radio frequency tables";
+ case CSR_PSKEY_RADIOTEST_CDMA_LO_REF_LIMITS:
+ return "LO frequency reference limits for CDMA in radiotest";
+ case CSR_PSKEY_INITIAL_BOOTMODE:
+ return "Initial device bootmode";
+ case CSR_PSKEY_ONCHIP_HCI_CLIENT:
+ return "HCI traffic routed internally";
+ case CSR_PSKEY_RX_ATTEN_BACKOFF:
+ return "Receiver attenuation back-off";
+ case CSR_PSKEY_RX_ATTEN_UPDATE_RATE:
+ return "Receiver attenuation update rate";
+ case CSR_PSKEY_SYNTH_TXRX_THRESHOLDS:
+ return "Local oscillator tuning voltage limits for tx and rx";
+ case CSR_PSKEY_MIN_WAIT_STATES:
+ return "Flash wait state indicator";
+ case CSR_PSKEY_RSSI_CORRECTION:
+ return "RSSI correction factor.";
+ case CSR_PSKEY_SCHED_THROTTLE_TIMEOUT:
+ return "Scheduler performance control.";
+ case CSR_PSKEY_DEEP_SLEEP_USE_EXTERNAL_CLOCK:
+ return "Deep sleep uses external 32 kHz clock source";
+ case CSR_PSKEY_TRIM_RADIO_FILTERS:
+ return "Trim rx and tx radio filters if true.";
+ case CSR_PSKEY_TRANSMIT_OFFSET:
+ return "Transmit offset in units of 62.5 kHz";
+ case CSR_PSKEY_USB_VM_CONTROL:
+ return "VM application will supply USB descriptors";
+ case CSR_PSKEY_MR_ANA_RX_FTRIM:
+ return "Medium rate value for the ANA_RX_FTRIM register";
+ case CSR_PSKEY_I2C_CONFIG:
+ return "I2C configuration";
+ case CSR_PSKEY_IQ_LVL_RX:
+ return "IQ demand level for reception";
+ case CSR_PSKEY_MR_TX_FILTER_CONFIG:
+ return "TX filter configuration used for enhanced data rate";
+ case CSR_PSKEY_MR_TX_CONFIG2:
+ return "TX filter configuration used for enhanced data rate";
+ case CSR_PSKEY_USB_DONT_RESET_BOOTMODE_ON_HOST_RESET:
+ return "Don't reset bootmode if USB host resets";
+ case CSR_PSKEY_LC_USE_THROTTLING:
+ return "Adjust packet selection on packet error rate";
+ case CSR_PSKEY_CHARGER_TRIM:
+ return "Trim value for the current charger";
+ case CSR_PSKEY_CLOCK_REQUEST_FEATURES:
+ return "Clock request is tristated if enabled";
+ case CSR_PSKEY_TRANSMIT_OFFSET_CLASS1:
+ return "Transmit offset / 62.5 kHz for class 1 radios";
+ case CSR_PSKEY_TX_AVOID_PA_CLASS1_PIO:
+ return "PIO line asserted in class1 operation to avoid PA";
+ case CSR_PSKEY_MR_PIO_CONFIG:
+ return "PIO line asserted in class1 operation to avoid PA";
+ case CSR_PSKEY_UART_CONFIG2:
+ return "The UART Sampling point";
+ case CSR_PSKEY_CLASS1_IQ_LVL:
+ return "IQ demand level for class 1 power level";
+ case CSR_PSKEY_CLASS1_TX_CONFIG2:
+ return "TX filter configuration used for class 1 tx power";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1:
+ return "Temperature for given internal PA adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1:
+ return "Temperature for given internal PA adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR:
+ return "Temperature adjustment for TX_PRE_LVL in EDR";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER:
+ return "Temperature for a given TX_BB in EDR header";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD:
+ return "Temperature for a given TX_BB in EDR payload";
+ case CSR_PSKEY_RX_MR_EQ_TAPS:
+ return "Adjust receiver configuration for EDR";
+ case CSR_PSKEY_TX_PRE_LVL_CLASS1:
+ return "TX pre-amplifier level in class 1 operation";
+ case CSR_PSKEY_ANALOGUE_ATTENUATOR:
+ return "TX analogue attenuator setting";
+ case CSR_PSKEY_MR_RX_FILTER_TRIM:
+ return "Trim for receiver used in EDR.";
+ case CSR_PSKEY_MR_RX_FILTER_RESPONSE:
+ return "Filter response for receiver used in EDR.";
+ case CSR_PSKEY_PIO_WAKEUP_STATE:
+ return "PIO deep sleep wake up state ";
+ case CSR_PSKEY_MR_TX_IF_ATTEN_OFF_TEMP:
+ return "TX IF atten off temperature when using EDR.";
+ case CSR_PSKEY_LO_DIV_LATCH_BYPASS:
+ return "Bypass latch for LO dividers";
+ case CSR_PSKEY_LO_VCO_STANDBY:
+ return "Use standby mode for the LO VCO";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_SHIFT:
+ return "Slow clock sampling filter constant";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_DIVIDER:
+ return "Slow clock filter fractional threshold";
+ case CSR_PSKEY_USB_ATTRIBUTES_POWER:
+ return "USB self powered";
+ case CSR_PSKEY_USB_ATTRIBUTES_WAKEUP:
+ return "USB responds to wake-up";
+ case CSR_PSKEY_DFU_ATTRIBUTES_MANIFESTATION_TOLERANT:
+ return "DFU manifestation tolerant";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_UPLOAD:
+ return "DFU can upload";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_DOWNLOAD:
+ return "DFU can download";
+ case CSR_PSKEY_UART_CONFIG_STOP_BITS:
+ return "UART: stop bits";
+ case CSR_PSKEY_UART_CONFIG_PARITY_BIT:
+ return "UART: parity bit";
+ case CSR_PSKEY_UART_CONFIG_FLOW_CTRL_EN:
+ return "UART: hardware flow control";
+ case CSR_PSKEY_UART_CONFIG_RTS_AUTO_EN:
+ return "UART: RTS auto-enabled";
+ case CSR_PSKEY_UART_CONFIG_RTS:
+ return "UART: RTS asserted";
+ case CSR_PSKEY_UART_CONFIG_TX_ZERO_EN:
+ return "UART: TX zero enable";
+ case CSR_PSKEY_UART_CONFIG_NON_BCSP_EN:
+ return "UART: enable BCSP-specific hardware";
+ case CSR_PSKEY_UART_CONFIG_RX_RATE_DELAY:
+ return "UART: RX rate delay";
+ case CSR_PSKEY_UART_SEQ_TIMEOUT:
+ return "UART: BCSP ack timeout";
+ case CSR_PSKEY_UART_SEQ_RETRIES:
+ return "UART: retry limit in sequencing layer";
+ case CSR_PSKEY_UART_SEQ_WINSIZE:
+ return "UART: BCSP transmit window size";
+ case CSR_PSKEY_UART_USE_CRC_ON_TX:
+ return "UART: use BCSP CRCs";
+ case CSR_PSKEY_UART_HOST_INITIAL_STATE:
+ return "UART: initial host state";
+ case CSR_PSKEY_UART_HOST_ATTENTION_SPAN:
+ return "UART: host attention span";
+ case CSR_PSKEY_UART_HOST_WAKEUP_TIME:
+ return "UART: host wakeup time";
+ case CSR_PSKEY_UART_HOST_WAKEUP_WAIT:
+ return "UART: host wakeup wait";
+ case CSR_PSKEY_BCSP_LM_MODE:
+ return "BCSP link establishment mode";
+ case CSR_PSKEY_BCSP_LM_SYNC_RETRIES:
+ return "BCSP link establishment sync retries";
+ case CSR_PSKEY_BCSP_LM_TSHY:
+ return "BCSP link establishment Tshy";
+ case CSR_PSKEY_UART_DFU_CONFIG_STOP_BITS:
+ return "DFU mode UART: stop bits";
+ case CSR_PSKEY_UART_DFU_CONFIG_PARITY_BIT:
+ return "DFU mode UART: parity bit";
+ case CSR_PSKEY_UART_DFU_CONFIG_FLOW_CTRL_EN:
+ return "DFU mode UART: hardware flow control";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS_AUTO_EN:
+ return "DFU mode UART: RTS auto-enabled";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS:
+ return "DFU mode UART: RTS asserted";
+ case CSR_PSKEY_UART_DFU_CONFIG_TX_ZERO_EN:
+ return "DFU mode UART: TX zero enable";
+ case CSR_PSKEY_UART_DFU_CONFIG_NON_BCSP_EN:
+ return "DFU mode UART: enable BCSP-specific hardware";
+ case CSR_PSKEY_UART_DFU_CONFIG_RX_RATE_DELAY:
+ return "DFU mode UART: RX rate delay";
+ case CSR_PSKEY_AMUX_AIO0:
+ return "Multiplexer for AIO 0";
+ case CSR_PSKEY_AMUX_AIO1:
+ return "Multiplexer for AIO 1";
+ case CSR_PSKEY_AMUX_AIO2:
+ return "Multiplexer for AIO 2";
+ case CSR_PSKEY_AMUX_AIO3:
+ return "Multiplexer for AIO 3";
+ case CSR_PSKEY_LOCAL_NAME_SIMPLIFIED:
+ return "Local Name (simplified)";
+ case CSR_PSKEY_EXTENDED_STUB:
+ return "Extended stub";
+ default:
+ return "Unknown";
+ }
+}
+
+char *csr_pskeytoval(uint16_t pskey)
+{
+ switch (pskey) {
+ case CSR_PSKEY_BDADDR:
+ return "BDADDR";
+ case CSR_PSKEY_COUNTRYCODE:
+ return "COUNTRYCODE";
+ case CSR_PSKEY_CLASSOFDEVICE:
+ return "CLASSOFDEVICE";
+ case CSR_PSKEY_DEVICE_DRIFT:
+ return "DEVICE_DRIFT";
+ case CSR_PSKEY_DEVICE_JITTER:
+ return "DEVICE_JITTER";
+ case CSR_PSKEY_MAX_ACLS:
+ return "MAX_ACLS";
+ case CSR_PSKEY_MAX_SCOS:
+ return "MAX_SCOS";
+ case CSR_PSKEY_MAX_REMOTE_MASTERS:
+ return "MAX_REMOTE_MASTERS";
+ case CSR_PSKEY_ENABLE_MASTERY_WITH_SLAVERY:
+ return "ENABLE_MASTERY_WITH_SLAVERY";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKT_LEN:
+ return "H_HC_FC_MAX_ACL_PKT_LEN";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKT_LEN:
+ return "H_HC_FC_MAX_SCO_PKT_LEN";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKTS:
+ return "H_HC_FC_MAX_ACL_PKTS";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKTS:
+ return "H_HC_FC_MAX_SCO_PKTS";
+ case CSR_PSKEY_LC_FC_BUFFER_LOW_WATER_MARK:
+ return "LC_FC_BUFFER_LOW_WATER_MARK";
+ case CSR_PSKEY_LC_MAX_TX_POWER:
+ return "LC_MAX_TX_POWER";
+ case CSR_PSKEY_TX_GAIN_RAMP:
+ return "TX_GAIN_RAMP";
+ case CSR_PSKEY_LC_POWER_TABLE:
+ return "LC_POWER_TABLE";
+ case CSR_PSKEY_LC_PEER_POWER_PERIOD:
+ return "LC_PEER_POWER_PERIOD";
+ case CSR_PSKEY_LC_FC_POOLS_LOW_WATER_MARK:
+ return "LC_FC_POOLS_LOW_WATER_MARK";
+ case CSR_PSKEY_LC_DEFAULT_TX_POWER:
+ return "LC_DEFAULT_TX_POWER";
+ case CSR_PSKEY_LC_RSSI_GOLDEN_RANGE:
+ return "LC_RSSI_GOLDEN_RANGE";
+ case CSR_PSKEY_LC_COMBO_DISABLE_PIO_MASK:
+ return "LC_COMBO_DISABLE_PIO_MASK";
+ case CSR_PSKEY_LC_COMBO_PRIORITY_PIO_MASK:
+ return "LC_COMBO_PRIORITY_PIO_MASK";
+ case CSR_PSKEY_LC_COMBO_DOT11_CHANNEL_PIO_BASE:
+ return "LC_COMBO_DOT11_CHANNEL_PIO_BASE";
+ case CSR_PSKEY_LC_COMBO_DOT11_BLOCK_CHANNELS:
+ return "LC_COMBO_DOT11_BLOCK_CHANNELS";
+ case CSR_PSKEY_LC_MAX_TX_POWER_NO_RSSI:
+ return "LC_MAX_TX_POWER_NO_RSSI";
+ case CSR_PSKEY_LC_CONNECTION_RX_WINDOW:
+ return "LC_CONNECTION_RX_WINDOW";
+ case CSR_PSKEY_LC_COMBO_DOT11_TX_PROTECTION_MODE:
+ return "LC_COMBO_DOT11_TX_PROTECTION_MODE";
+ case CSR_PSKEY_LC_ENHANCED_POWER_TABLE:
+ return "LC_ENHANCED_POWER_TABLE";
+ case CSR_PSKEY_LC_WIDEBAND_RSSI_CONFIG:
+ return "LC_WIDEBAND_RSSI_CONFIG";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_LEAD:
+ return "LC_COMBO_DOT11_PRIORITY_LEAD";
+ case CSR_PSKEY_BT_CLOCK_INIT:
+ return "BT_CLOCK_INIT";
+ case CSR_PSKEY_TX_MR_MOD_DELAY:
+ return "TX_MR_MOD_DELAY";
+ case CSR_PSKEY_RX_MR_SYNC_TIMING:
+ return "RX_MR_SYNC_TIMING";
+ case CSR_PSKEY_RX_MR_SYNC_CONFIG:
+ return "RX_MR_SYNC_CONFIG";
+ case CSR_PSKEY_LC_LOST_SYNC_SLOTS:
+ return "LC_LOST_SYNC_SLOTS";
+ case CSR_PSKEY_RX_MR_SAMP_CONFIG:
+ return "RX_MR_SAMP_CONFIG";
+ case CSR_PSKEY_AGC_HYST_LEVELS:
+ return "AGC_HYST_LEVELS";
+ case CSR_PSKEY_RX_LEVEL_LOW_SIGNAL:
+ return "RX_LEVEL_LOW_SIGNAL";
+ case CSR_PSKEY_AGC_IQ_LVL_VALUES:
+ return "AGC_IQ_LVL_VALUES";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_12DB:
+ return "MR_FTRIM_OFFSET_12DB";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_6DB:
+ return "MR_FTRIM_OFFSET_6DB";
+ case CSR_PSKEY_NO_CAL_ON_BOOT:
+ return "NO_CAL_ON_BOOT";
+ case CSR_PSKEY_RSSI_HI_TARGET:
+ return "RSSI_HI_TARGET";
+ case CSR_PSKEY_PREFERRED_MIN_ATTENUATION:
+ return "PREFERRED_MIN_ATTENUATION";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_OVERRIDE:
+ return "LC_COMBO_DOT11_PRIORITY_OVERRIDE";
+ case CSR_PSKEY_LC_MULTISLOT_HOLDOFF:
+ return "LC_MULTISLOT_HOLDOFF";
+ case CSR_PSKEY_FREE_KEY_PIGEON_HOLE:
+ return "FREE_KEY_PIGEON_HOLE";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR0:
+ return "LINK_KEY_BD_ADDR0";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR1:
+ return "LINK_KEY_BD_ADDR1";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR2:
+ return "LINK_KEY_BD_ADDR2";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR3:
+ return "LINK_KEY_BD_ADDR3";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR4:
+ return "LINK_KEY_BD_ADDR4";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR5:
+ return "LINK_KEY_BD_ADDR5";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR6:
+ return "LINK_KEY_BD_ADDR6";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR7:
+ return "LINK_KEY_BD_ADDR7";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR8:
+ return "LINK_KEY_BD_ADDR8";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR9:
+ return "LINK_KEY_BD_ADDR9";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR10:
+ return "LINK_KEY_BD_ADDR10";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR11:
+ return "LINK_KEY_BD_ADDR11";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR12:
+ return "LINK_KEY_BD_ADDR12";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR13:
+ return "LINK_KEY_BD_ADDR13";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR14:
+ return "LINK_KEY_BD_ADDR14";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR15:
+ return "LINK_KEY_BD_ADDR15";
+ case CSR_PSKEY_ENC_KEY_LMIN:
+ return "ENC_KEY_LMIN";
+ case CSR_PSKEY_ENC_KEY_LMAX:
+ return "ENC_KEY_LMAX";
+ case CSR_PSKEY_LOCAL_SUPPORTED_FEATURES:
+ return "LOCAL_SUPPORTED_FEATURES";
+ case CSR_PSKEY_LM_USE_UNIT_KEY:
+ return "LM_USE_UNIT_KEY";
+ case CSR_PSKEY_HCI_NOP_DISABLE:
+ return "HCI_NOP_DISABLE";
+ case CSR_PSKEY_LM_MAX_EVENT_FILTERS:
+ return "LM_MAX_EVENT_FILTERS";
+ case CSR_PSKEY_LM_USE_ENC_MODE_BROADCAST:
+ return "LM_USE_ENC_MODE_BROADCAST";
+ case CSR_PSKEY_LM_TEST_SEND_ACCEPTED_TWICE:
+ return "LM_TEST_SEND_ACCEPTED_TWICE";
+ case CSR_PSKEY_LM_MAX_PAGE_HOLD_TIME:
+ return "LM_MAX_PAGE_HOLD_TIME";
+ case CSR_PSKEY_AFH_ADAPTATION_RESPONSE_TIME:
+ return "AFH_ADAPTATION_RESPONSE_TIME";
+ case CSR_PSKEY_AFH_OPTIONS:
+ return "AFH_OPTIONS";
+ case CSR_PSKEY_AFH_RSSI_RUN_PERIOD:
+ return "AFH_RSSI_RUN_PERIOD";
+ case CSR_PSKEY_AFH_REENABLE_CHANNEL_TIME:
+ return "AFH_REENABLE_CHANNEL_TIME";
+ case CSR_PSKEY_NO_DROP_ON_ACR_MS_FAIL:
+ return "NO_DROP_ON_ACR_MS_FAIL";
+ case CSR_PSKEY_MAX_PRIVATE_KEYS:
+ return "MAX_PRIVATE_KEYS";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR0:
+ return "PRIVATE_LINK_KEY_BD_ADDR0";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR1:
+ return "PRIVATE_LINK_KEY_BD_ADDR1";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR2:
+ return "PRIVATE_LINK_KEY_BD_ADDR2";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR3:
+ return "PRIVATE_LINK_KEY_BD_ADDR3";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR4:
+ return "PRIVATE_LINK_KEY_BD_ADDR4";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR5:
+ return "PRIVATE_LINK_KEY_BD_ADDR5";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR6:
+ return "PRIVATE_LINK_KEY_BD_ADDR6";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR7:
+ return "PRIVATE_LINK_KEY_BD_ADDR7";
+ case CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS:
+ return "LOCAL_SUPPORTED_COMMANDS";
+ case CSR_PSKEY_LM_MAX_ABSENCE_INDEX:
+ return "LM_MAX_ABSENCE_INDEX";
+ case CSR_PSKEY_DEVICE_NAME:
+ return "DEVICE_NAME";
+ case CSR_PSKEY_AFH_RSSI_THRESHOLD:
+ return "AFH_RSSI_THRESHOLD";
+ case CSR_PSKEY_LM_CASUAL_SCAN_INTERVAL:
+ return "LM_CASUAL_SCAN_INTERVAL";
+ case CSR_PSKEY_AFH_MIN_MAP_CHANGE:
+ return "AFH_MIN_MAP_CHANGE";
+ case CSR_PSKEY_AFH_RSSI_LP_RUN_PERIOD:
+ return "AFH_RSSI_LP_RUN_PERIOD";
+ case CSR_PSKEY_HCI_LMP_LOCAL_VERSION:
+ return "HCI_LMP_LOCAL_VERSION";
+ case CSR_PSKEY_LMP_REMOTE_VERSION:
+ return "LMP_REMOTE_VERSION";
+ case CSR_PSKEY_HOLD_ERROR_MESSAGE_NUMBER:
+ return "HOLD_ERROR_MESSAGE_NUMBER";
+ case CSR_PSKEY_DFU_ATTRIBUTES:
+ return "DFU_ATTRIBUTES";
+ case CSR_PSKEY_DFU_DETACH_TO:
+ return "DFU_DETACH_TO";
+ case CSR_PSKEY_DFU_TRANSFER_SIZE:
+ return "DFU_TRANSFER_SIZE";
+ case CSR_PSKEY_DFU_ENABLE:
+ return "DFU_ENABLE";
+ case CSR_PSKEY_DFU_LIN_REG_ENABLE:
+ return "DFU_LIN_REG_ENABLE";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_MSB:
+ return "DFUENC_VMAPP_PK_MODULUS_MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_LSB:
+ return "DFUENC_VMAPP_PK_MODULUS_LSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_M_DASH:
+ return "DFUENC_VMAPP_PK_M_DASH";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_MSB:
+ return "DFUENC_VMAPP_PK_R2N_MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_LSB:
+ return "DFUENC_VMAPP_PK_R2N_LSB";
+ case CSR_PSKEY_BCSP_LM_PS_BLOCK:
+ return "BCSP_LM_PS_BLOCK";
+ case CSR_PSKEY_HOSTIO_FC_PS_BLOCK:
+ return "HOSTIO_FC_PS_BLOCK";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO0:
+ return "HOSTIO_PROTOCOL_INFO0";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO1:
+ return "HOSTIO_PROTOCOL_INFO1";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO2:
+ return "HOSTIO_PROTOCOL_INFO2";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO3:
+ return "HOSTIO_PROTOCOL_INFO3";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO4:
+ return "HOSTIO_PROTOCOL_INFO4";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO5:
+ return "HOSTIO_PROTOCOL_INFO5";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO6:
+ return "HOSTIO_PROTOCOL_INFO6";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO7:
+ return "HOSTIO_PROTOCOL_INFO7";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO8:
+ return "HOSTIO_PROTOCOL_INFO8";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO9:
+ return "HOSTIO_PROTOCOL_INFO9";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO10:
+ return "HOSTIO_PROTOCOL_INFO10";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO11:
+ return "HOSTIO_PROTOCOL_INFO11";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO12:
+ return "HOSTIO_PROTOCOL_INFO12";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO13:
+ return "HOSTIO_PROTOCOL_INFO13";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO14:
+ return "HOSTIO_PROTOCOL_INFO14";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO15:
+ return "HOSTIO_PROTOCOL_INFO15";
+ case CSR_PSKEY_HOSTIO_UART_RESET_TIMEOUT:
+ return "HOSTIO_UART_RESET_TIMEOUT";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN:
+ return "HOSTIO_USE_HCI_EXTN";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN_CCFC:
+ return "HOSTIO_USE_HCI_EXTN_CCFC";
+ case CSR_PSKEY_HOSTIO_HCI_EXTN_PAYLOAD_SIZE:
+ return "HOSTIO_HCI_EXTN_PAYLOAD_SIZE";
+ case CSR_PSKEY_BCSP_LM_CNF_CNT_LIMIT:
+ return "BCSP_LM_CNF_CNT_LIMIT";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM:
+ return "HOSTIO_MAP_SCO_PCM";
+ case CSR_PSKEY_HOSTIO_AWKWARD_PCM_SYNC:
+ return "HOSTIO_AWKWARD_PCM_SYNC";
+ case CSR_PSKEY_HOSTIO_BREAK_POLL_PERIOD:
+ return "HOSTIO_BREAK_POLL_PERIOD";
+ case CSR_PSKEY_HOSTIO_MIN_UART_HCI_SCO_SIZE:
+ return "HOSTIO_MIN_UART_HCI_SCO_SIZE";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_CODEC:
+ return "HOSTIO_MAP_SCO_CODEC";
+ case CSR_PSKEY_PCM_CVSD_TX_HI_FREQ_BOOST:
+ return "PCM_CVSD_TX_HI_FREQ_BOOST";
+ case CSR_PSKEY_PCM_CVSD_RX_HI_FREQ_BOOST:
+ return "PCM_CVSD_RX_HI_FREQ_BOOST";
+ case CSR_PSKEY_PCM_CONFIG32:
+ return "PCM_CONFIG32";
+ case CSR_PSKEY_USE_OLD_BCSP_LE:
+ return "USE_OLD_BCSP_LE";
+ case CSR_PSKEY_PCM_CVSD_USE_NEW_FILTER:
+ return "PCM_CVSD_USE_NEW_FILTER";
+ case CSR_PSKEY_PCM_FORMAT:
+ return "PCM_FORMAT";
+ case CSR_PSKEY_CODEC_OUT_GAIN:
+ return "CODEC_OUT_GAIN";
+ case CSR_PSKEY_CODEC_IN_GAIN:
+ return "CODEC_IN_GAIN";
+ case CSR_PSKEY_CODEC_PIO:
+ return "CODEC_PIO";
+ case CSR_PSKEY_PCM_LOW_JITTER_CONFIG:
+ return "PCM_LOW_JITTER_CONFIG";
+ case CSR_PSKEY_HOSTIO_SCO_PCM_THRESHOLDS:
+ return "HOSTIO_SCO_PCM_THRESHOLDS";
+ case CSR_PSKEY_HOSTIO_SCO_HCI_THRESHOLDS:
+ return "HOSTIO_SCO_HCI_THRESHOLDS";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM_SLOT:
+ return "HOSTIO_MAP_SCO_PCM_SLOT";
+ case CSR_PSKEY_UART_BAUDRATE:
+ return "UART_BAUDRATE";
+ case CSR_PSKEY_UART_CONFIG_BCSP:
+ return "UART_CONFIG_BCSP";
+ case CSR_PSKEY_UART_CONFIG_H4:
+ return "UART_CONFIG_H4";
+ case CSR_PSKEY_UART_CONFIG_H5:
+ return "UART_CONFIG_H5";
+ case CSR_PSKEY_UART_CONFIG_USR:
+ return "UART_CONFIG_USR";
+ case CSR_PSKEY_UART_TX_CRCS:
+ return "UART_TX_CRCS";
+ case CSR_PSKEY_UART_ACK_TIMEOUT:
+ return "UART_ACK_TIMEOUT";
+ case CSR_PSKEY_UART_TX_MAX_ATTEMPTS:
+ return "UART_TX_MAX_ATTEMPTS";
+ case CSR_PSKEY_UART_TX_WINDOW_SIZE:
+ return "UART_TX_WINDOW_SIZE";
+ case CSR_PSKEY_UART_HOST_WAKE:
+ return "UART_HOST_WAKE";
+ case CSR_PSKEY_HOSTIO_THROTTLE_TIMEOUT:
+ return "HOSTIO_THROTTLE_TIMEOUT";
+ case CSR_PSKEY_PCM_ALWAYS_ENABLE:
+ return "PCM_ALWAYS_ENABLE";
+ case CSR_PSKEY_UART_HOST_WAKE_SIGNAL:
+ return "UART_HOST_WAKE_SIGNAL";
+ case CSR_PSKEY_UART_CONFIG_H4DS:
+ return "UART_CONFIG_H4DS";
+ case CSR_PSKEY_H4DS_WAKE_DURATION:
+ return "H4DS_WAKE_DURATION";
+ case CSR_PSKEY_H4DS_MAXWU:
+ return "H4DS_MAXWU";
+ case CSR_PSKEY_H4DS_LE_TIMER_PERIOD:
+ return "H4DS_LE_TIMER_PERIOD";
+ case CSR_PSKEY_H4DS_TWU_TIMER_PERIOD:
+ return "H4DS_TWU_TIMER_PERIOD";
+ case CSR_PSKEY_H4DS_UART_IDLE_TIMER_PERIOD:
+ return "H4DS_UART_IDLE_TIMER_PERIOD";
+ case CSR_PSKEY_ANA_FTRIM:
+ return "ANA_FTRIM";
+ case CSR_PSKEY_WD_TIMEOUT:
+ return "WD_TIMEOUT";
+ case CSR_PSKEY_WD_PERIOD:
+ return "WD_PERIOD";
+ case CSR_PSKEY_HOST_INTERFACE:
+ return "HOST_INTERFACE";
+ case CSR_PSKEY_HQ_HOST_TIMEOUT:
+ return "HQ_HOST_TIMEOUT";
+ case CSR_PSKEY_HQ_ACTIVE:
+ return "HQ_ACTIVE";
+ case CSR_PSKEY_BCCMD_SECURITY_ACTIVE:
+ return "BCCMD_SECURITY_ACTIVE";
+ case CSR_PSKEY_ANA_FREQ:
+ return "ANA_FREQ";
+ case CSR_PSKEY_PIO_PROTECT_MASK:
+ return "PIO_PROTECT_MASK";
+ case CSR_PSKEY_PMALLOC_SIZES:
+ return "PMALLOC_SIZES";
+ case CSR_PSKEY_UART_BAUD_RATE:
+ return "UART_BAUD_RATE";
+ case CSR_PSKEY_UART_CONFIG:
+ return "UART_CONFIG";
+ case CSR_PSKEY_STUB:
+ return "STUB";
+ case CSR_PSKEY_TXRX_PIO_CONTROL:
+ return "TXRX_PIO_CONTROL";
+ case CSR_PSKEY_ANA_RX_LEVEL:
+ return "ANA_RX_LEVEL";
+ case CSR_PSKEY_ANA_RX_FTRIM:
+ return "ANA_RX_FTRIM";
+ case CSR_PSKEY_PSBC_DATA_VERSION:
+ return "PSBC_DATA_VERSION";
+ case CSR_PSKEY_PCM0_ATTENUATION:
+ return "PCM0_ATTENUATION";
+ case CSR_PSKEY_LO_LVL_MAX:
+ return "LO_LVL_MAX";
+ case CSR_PSKEY_LO_ADC_AMPL_MIN:
+ return "LO_ADC_AMPL_MIN";
+ case CSR_PSKEY_LO_ADC_AMPL_MAX:
+ return "LO_ADC_AMPL_MAX";
+ case CSR_PSKEY_IQ_TRIM_CHANNEL:
+ return "IQ_TRIM_CHANNEL";
+ case CSR_PSKEY_IQ_TRIM_GAIN:
+ return "IQ_TRIM_GAIN";
+ case CSR_PSKEY_IQ_TRIM_ENABLE:
+ return "IQ_TRIM_ENABLE";
+ case CSR_PSKEY_TX_OFFSET_HALF_MHZ:
+ return "TX_OFFSET_HALF_MHZ";
+ case CSR_PSKEY_GBL_MISC_ENABLES:
+ return "GBL_MISC_ENABLES";
+ case CSR_PSKEY_UART_SLEEP_TIMEOUT:
+ return "UART_SLEEP_TIMEOUT";
+ case CSR_PSKEY_DEEP_SLEEP_STATE:
+ return "DEEP_SLEEP_STATE";
+ case CSR_PSKEY_IQ_ENABLE_PHASE_TRIM:
+ return "IQ_ENABLE_PHASE_TRIM";
+ case CSR_PSKEY_HCI_HANDLE_FREEZE_PERIOD:
+ return "HCI_HANDLE_FREEZE_PERIOD";
+ case CSR_PSKEY_MAX_FROZEN_HCI_HANDLES:
+ return "MAX_FROZEN_HCI_HANDLES";
+ case CSR_PSKEY_PAGETABLE_DESTRUCTION_DELAY:
+ return "PAGETABLE_DESTRUCTION_DELAY";
+ case CSR_PSKEY_IQ_TRIM_PIO_SETTINGS:
+ return "IQ_TRIM_PIO_SETTINGS";
+ case CSR_PSKEY_USE_EXTERNAL_CLOCK:
+ return "USE_EXTERNAL_CLOCK";
+ case CSR_PSKEY_DEEP_SLEEP_WAKE_CTS:
+ return "DEEP_SLEEP_WAKE_CTS";
+ case CSR_PSKEY_FC_HC2H_FLUSH_DELAY:
+ return "FC_HC2H_FLUSH_DELAY";
+ case CSR_PSKEY_RX_HIGHSIDE:
+ return "RX_HIGHSIDE";
+ case CSR_PSKEY_TX_PRE_LVL:
+ return "TX_PRE_LVL";
+ case CSR_PSKEY_RX_SINGLE_ENDED:
+ return "RX_SINGLE_ENDED";
+ case CSR_PSKEY_TX_FILTER_CONFIG:
+ return "TX_FILTER_CONFIG";
+ case CSR_PSKEY_CLOCK_REQUEST_ENABLE:
+ return "CLOCK_REQUEST_ENABLE";
+ case CSR_PSKEY_RX_MIN_ATTEN:
+ return "RX_MIN_ATTEN";
+ case CSR_PSKEY_XTAL_TARGET_AMPLITUDE:
+ return "XTAL_TARGET_AMPLITUDE";
+ case CSR_PSKEY_PCM_MIN_CPU_CLOCK:
+ return "PCM_MIN_CPU_CLOCK";
+ case CSR_PSKEY_HOST_INTERFACE_PIO_USB:
+ return "HOST_INTERFACE_PIO_USB";
+ case CSR_PSKEY_CPU_IDLE_MODE:
+ return "CPU_IDLE_MODE";
+ case CSR_PSKEY_DEEP_SLEEP_CLEAR_RTS:
+ return "DEEP_SLEEP_CLEAR_RTS";
+ case CSR_PSKEY_RF_RESONANCE_TRIM:
+ return "RF_RESONANCE_TRIM";
+ case CSR_PSKEY_DEEP_SLEEP_PIO_WAKE:
+ return "DEEP_SLEEP_PIO_WAKE";
+ case CSR_PSKEY_DRAIN_BORE_TIMERS:
+ return "DRAIN_BORE_TIMERS";
+ case CSR_PSKEY_DRAIN_TX_POWER_BASE:
+ return "DRAIN_TX_POWER_BASE";
+ case CSR_PSKEY_MODULE_ID:
+ return "MODULE_ID";
+ case CSR_PSKEY_MODULE_DESIGN:
+ return "MODULE_DESIGN";
+ case CSR_PSKEY_MODULE_SECURITY_CODE:
+ return "MODULE_SECURITY_CODE";
+ case CSR_PSKEY_VM_DISABLE:
+ return "VM_DISABLE";
+ case CSR_PSKEY_MOD_MANUF0:
+ return "MOD_MANUF0";
+ case CSR_PSKEY_MOD_MANUF1:
+ return "MOD_MANUF1";
+ case CSR_PSKEY_MOD_MANUF2:
+ return "MOD_MANUF2";
+ case CSR_PSKEY_MOD_MANUF3:
+ return "MOD_MANUF3";
+ case CSR_PSKEY_MOD_MANUF4:
+ return "MOD_MANUF4";
+ case CSR_PSKEY_MOD_MANUF5:
+ return "MOD_MANUF5";
+ case CSR_PSKEY_MOD_MANUF6:
+ return "MOD_MANUF6";
+ case CSR_PSKEY_MOD_MANUF7:
+ return "MOD_MANUF7";
+ case CSR_PSKEY_MOD_MANUF8:
+ return "MOD_MANUF8";
+ case CSR_PSKEY_MOD_MANUF9:
+ return "MOD_MANUF9";
+ case CSR_PSKEY_DUT_VM_DISABLE:
+ return "DUT_VM_DISABLE";
+ case CSR_PSKEY_USR0:
+ return "USR0";
+ case CSR_PSKEY_USR1:
+ return "USR1";
+ case CSR_PSKEY_USR2:
+ return "USR2";
+ case CSR_PSKEY_USR3:
+ return "USR3";
+ case CSR_PSKEY_USR4:
+ return "USR4";
+ case CSR_PSKEY_USR5:
+ return "USR5";
+ case CSR_PSKEY_USR6:
+ return "USR6";
+ case CSR_PSKEY_USR7:
+ return "USR7";
+ case CSR_PSKEY_USR8:
+ return "USR8";
+ case CSR_PSKEY_USR9:
+ return "USR9";
+ case CSR_PSKEY_USR10:
+ return "USR10";
+ case CSR_PSKEY_USR11:
+ return "USR11";
+ case CSR_PSKEY_USR12:
+ return "USR12";
+ case CSR_PSKEY_USR13:
+ return "USR13";
+ case CSR_PSKEY_USR14:
+ return "USR14";
+ case CSR_PSKEY_USR15:
+ return "USR15";
+ case CSR_PSKEY_USR16:
+ return "USR16";
+ case CSR_PSKEY_USR17:
+ return "USR17";
+ case CSR_PSKEY_USR18:
+ return "USR18";
+ case CSR_PSKEY_USR19:
+ return "USR19";
+ case CSR_PSKEY_USR20:
+ return "USR20";
+ case CSR_PSKEY_USR21:
+ return "USR21";
+ case CSR_PSKEY_USR22:
+ return "USR22";
+ case CSR_PSKEY_USR23:
+ return "USR23";
+ case CSR_PSKEY_USR24:
+ return "USR24";
+ case CSR_PSKEY_USR25:
+ return "USR25";
+ case CSR_PSKEY_USR26:
+ return "USR26";
+ case CSR_PSKEY_USR27:
+ return "USR27";
+ case CSR_PSKEY_USR28:
+ return "USR28";
+ case CSR_PSKEY_USR29:
+ return "USR29";
+ case CSR_PSKEY_USR30:
+ return "USR30";
+ case CSR_PSKEY_USR31:
+ return "USR31";
+ case CSR_PSKEY_USR32:
+ return "USR32";
+ case CSR_PSKEY_USR33:
+ return "USR33";
+ case CSR_PSKEY_USR34:
+ return "USR34";
+ case CSR_PSKEY_USR35:
+ return "USR35";
+ case CSR_PSKEY_USR36:
+ return "USR36";
+ case CSR_PSKEY_USR37:
+ return "USR37";
+ case CSR_PSKEY_USR38:
+ return "USR38";
+ case CSR_PSKEY_USR39:
+ return "USR39";
+ case CSR_PSKEY_USR40:
+ return "USR40";
+ case CSR_PSKEY_USR41:
+ return "USR41";
+ case CSR_PSKEY_USR42:
+ return "USR42";
+ case CSR_PSKEY_USR43:
+ return "USR43";
+ case CSR_PSKEY_USR44:
+ return "USR44";
+ case CSR_PSKEY_USR45:
+ return "USR45";
+ case CSR_PSKEY_USR46:
+ return "USR46";
+ case CSR_PSKEY_USR47:
+ return "USR47";
+ case CSR_PSKEY_USR48:
+ return "USR48";
+ case CSR_PSKEY_USR49:
+ return "USR49";
+ case CSR_PSKEY_USB_VERSION:
+ return "USB_VERSION";
+ case CSR_PSKEY_USB_DEVICE_CLASS_CODES:
+ return "USB_DEVICE_CLASS_CODES";
+ case CSR_PSKEY_USB_VENDOR_ID:
+ return "USB_VENDOR_ID";
+ case CSR_PSKEY_USB_PRODUCT_ID:
+ return "USB_PRODUCT_ID";
+ case CSR_PSKEY_USB_MANUF_STRING:
+ return "USB_MANUF_STRING";
+ case CSR_PSKEY_USB_PRODUCT_STRING:
+ return "USB_PRODUCT_STRING";
+ case CSR_PSKEY_USB_SERIAL_NUMBER_STRING:
+ return "USB_SERIAL_NUMBER_STRING";
+ case CSR_PSKEY_USB_CONFIG_STRING:
+ return "USB_CONFIG_STRING";
+ case CSR_PSKEY_USB_ATTRIBUTES:
+ return "USB_ATTRIBUTES";
+ case CSR_PSKEY_USB_MAX_POWER:
+ return "USB_MAX_POWER";
+ case CSR_PSKEY_USB_BT_IF_CLASS_CODES:
+ return "USB_BT_IF_CLASS_CODES";
+ case CSR_PSKEY_USB_LANGID:
+ return "USB_LANGID";
+ case CSR_PSKEY_USB_DFU_CLASS_CODES:
+ return "USB_DFU_CLASS_CODES";
+ case CSR_PSKEY_USB_DFU_PRODUCT_ID:
+ return "USB_DFU_PRODUCT_ID";
+ case CSR_PSKEY_USB_PIO_DETACH:
+ return "USB_PIO_DETACH";
+ case CSR_PSKEY_USB_PIO_WAKEUP:
+ return "USB_PIO_WAKEUP";
+ case CSR_PSKEY_USB_PIO_PULLUP:
+ return "USB_PIO_PULLUP";
+ case CSR_PSKEY_USB_PIO_VBUS:
+ return "USB_PIO_VBUS";
+ case CSR_PSKEY_USB_PIO_WAKE_TIMEOUT:
+ return "USB_PIO_WAKE_TIMEOUT";
+ case CSR_PSKEY_USB_PIO_RESUME:
+ return "USB_PIO_RESUME";
+ case CSR_PSKEY_USB_BT_SCO_IF_CLASS_CODES:
+ return "USB_BT_SCO_IF_CLASS_CODES";
+ case CSR_PSKEY_USB_SUSPEND_PIO_LEVEL:
+ return "USB_SUSPEND_PIO_LEVEL";
+ case CSR_PSKEY_USB_SUSPEND_PIO_DIR:
+ return "USB_SUSPEND_PIO_DIR";
+ case CSR_PSKEY_USB_SUSPEND_PIO_MASK:
+ return "USB_SUSPEND_PIO_MASK";
+ case CSR_PSKEY_USB_ENDPOINT_0_MAX_PACKET_SIZE:
+ return "USB_ENDPOINT_0_MAX_PACKET_SIZE";
+ case CSR_PSKEY_USB_CONFIG:
+ return "USB_CONFIG";
+ case CSR_PSKEY_RADIOTEST_ATTEN_INIT:
+ return "RADIOTEST_ATTEN_INIT";
+ case CSR_PSKEY_RADIOTEST_FIRST_TRIM_TIME:
+ return "RADIOTEST_FIRST_TRIM_TIME";
+ case CSR_PSKEY_RADIOTEST_SUBSEQUENT_TRIM_TIME:
+ return "RADIOTEST_SUBSEQUENT_TRIM_TIME";
+ case CSR_PSKEY_RADIOTEST_LO_LVL_TRIM_ENABLE:
+ return "RADIOTEST_LO_LVL_TRIM_ENABLE";
+ case CSR_PSKEY_RADIOTEST_DISABLE_MODULATION:
+ return "RADIOTEST_DISABLE_MODULATION";
+ case CSR_PSKEY_RFCOMM_FCON_THRESHOLD:
+ return "RFCOMM_FCON_THRESHOLD";
+ case CSR_PSKEY_RFCOMM_FCOFF_THRESHOLD:
+ return "RFCOMM_FCOFF_THRESHOLD";
+ case CSR_PSKEY_IPV6_STATIC_ADDR:
+ return "IPV6_STATIC_ADDR";
+ case CSR_PSKEY_IPV4_STATIC_ADDR:
+ return "IPV4_STATIC_ADDR";
+ case CSR_PSKEY_IPV6_STATIC_PREFIX_LEN:
+ return "IPV6_STATIC_PREFIX_LEN";
+ case CSR_PSKEY_IPV6_STATIC_ROUTER_ADDR:
+ return "IPV6_STATIC_ROUTER_ADDR";
+ case CSR_PSKEY_IPV4_STATIC_SUBNET_MASK:
+ return "IPV4_STATIC_SUBNET_MASK";
+ case CSR_PSKEY_IPV4_STATIC_ROUTER_ADDR:
+ return "IPV4_STATIC_ROUTER_ADDR";
+ case CSR_PSKEY_MDNS_NAME:
+ return "MDNS_NAME";
+ case CSR_PSKEY_FIXED_PIN:
+ return "FIXED_PIN";
+ case CSR_PSKEY_MDNS_PORT:
+ return "MDNS_PORT";
+ case CSR_PSKEY_MDNS_TTL:
+ return "MDNS_TTL";
+ case CSR_PSKEY_MDNS_IPV4_ADDR:
+ return "MDNS_IPV4_ADDR";
+ case CSR_PSKEY_ARP_CACHE_TIMEOUT:
+ return "ARP_CACHE_TIMEOUT";
+ case CSR_PSKEY_HFP_POWER_TABLE:
+ return "HFP_POWER_TABLE";
+ case CSR_PSKEY_DRAIN_BORE_TIMER_COUNTERS:
+ return "DRAIN_BORE_TIMER_COUNTERS";
+ case CSR_PSKEY_DRAIN_BORE_COUNTERS:
+ return "DRAIN_BORE_COUNTERS";
+ case CSR_PSKEY_LOOP_FILTER_TRIM:
+ return "LOOP_FILTER_TRIM";
+ case CSR_PSKEY_DRAIN_BORE_CURRENT_PEAK:
+ return "DRAIN_BORE_CURRENT_PEAK";
+ case CSR_PSKEY_VM_E2_CACHE_LIMIT:
+ return "VM_E2_CACHE_LIMIT";
+ case CSR_PSKEY_FORCE_16MHZ_REF_PIO:
+ return "FORCE_16MHZ_REF_PIO";
+ case CSR_PSKEY_CDMA_LO_REF_LIMITS:
+ return "CDMA_LO_REF_LIMITS";
+ case CSR_PSKEY_CDMA_LO_ERROR_LIMITS:
+ return "CDMA_LO_ERROR_LIMITS";
+ case CSR_PSKEY_CLOCK_STARTUP_DELAY:
+ return "CLOCK_STARTUP_DELAY";
+ case CSR_PSKEY_DEEP_SLEEP_CORRECTION_FACTOR:
+ return "DEEP_SLEEP_CORRECTION_FACTOR";
+ case CSR_PSKEY_TEMPERATURE_CALIBRATION:
+ return "TEMPERATURE_CALIBRATION";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA:
+ return "TEMPERATURE_VS_DELTA_INTERNAL_PA";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL:
+ return "TEMPERATURE_VS_DELTA_TX_PRE_LVL";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB:
+ return "TEMPERATURE_VS_DELTA_TX_BB";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_ANA_FTRIM:
+ return "TEMPERATURE_VS_DELTA_ANA_FTRIM";
+ case CSR_PSKEY_TEST_DELTA_OFFSET:
+ return "TEST_DELTA_OFFSET";
+ case CSR_PSKEY_RX_DYNAMIC_LVL_OFFSET:
+ return "RX_DYNAMIC_LVL_OFFSET";
+ case CSR_PSKEY_TEST_FORCE_OFFSET:
+ return "TEST_FORCE_OFFSET";
+ case CSR_PSKEY_RF_TRAP_BAD_DIVISION_RATIOS:
+ return "RF_TRAP_BAD_DIVISION_RATIOS";
+ case CSR_PSKEY_RADIOTEST_CDMA_LO_REF_LIMITS:
+ return "RADIOTEST_CDMA_LO_REF_LIMITS";
+ case CSR_PSKEY_INITIAL_BOOTMODE:
+ return "INITIAL_BOOTMODE";
+ case CSR_PSKEY_ONCHIP_HCI_CLIENT:
+ return "ONCHIP_HCI_CLIENT";
+ case CSR_PSKEY_RX_ATTEN_BACKOFF:
+ return "RX_ATTEN_BACKOFF";
+ case CSR_PSKEY_RX_ATTEN_UPDATE_RATE:
+ return "RX_ATTEN_UPDATE_RATE";
+ case CSR_PSKEY_SYNTH_TXRX_THRESHOLDS:
+ return "SYNTH_TXRX_THRESHOLDS";
+ case CSR_PSKEY_MIN_WAIT_STATES:
+ return "MIN_WAIT_STATES";
+ case CSR_PSKEY_RSSI_CORRECTION:
+ return "RSSI_CORRECTION";
+ case CSR_PSKEY_SCHED_THROTTLE_TIMEOUT:
+ return "SCHED_THROTTLE_TIMEOUT";
+ case CSR_PSKEY_DEEP_SLEEP_USE_EXTERNAL_CLOCK:
+ return "DEEP_SLEEP_USE_EXTERNAL_CLOCK";
+ case CSR_PSKEY_TRIM_RADIO_FILTERS:
+ return "TRIM_RADIO_FILTERS";
+ case CSR_PSKEY_TRANSMIT_OFFSET:
+ return "TRANSMIT_OFFSET";
+ case CSR_PSKEY_USB_VM_CONTROL:
+ return "USB_VM_CONTROL";
+ case CSR_PSKEY_MR_ANA_RX_FTRIM:
+ return "MR_ANA_RX_FTRIM";
+ case CSR_PSKEY_I2C_CONFIG:
+ return "I2C_CONFIG";
+ case CSR_PSKEY_IQ_LVL_RX:
+ return "IQ_LVL_RX";
+ case CSR_PSKEY_MR_TX_FILTER_CONFIG:
+ return "MR_TX_FILTER_CONFIG";
+ case CSR_PSKEY_MR_TX_CONFIG2:
+ return "MR_TX_CONFIG2";
+ case CSR_PSKEY_USB_DONT_RESET_BOOTMODE_ON_HOST_RESET:
+ return "USB_DONT_RESET_BOOTMODE_ON_HOST_RESET";
+ case CSR_PSKEY_LC_USE_THROTTLING:
+ return "LC_USE_THROTTLING";
+ case CSR_PSKEY_CHARGER_TRIM:
+ return "CHARGER_TRIM";
+ case CSR_PSKEY_CLOCK_REQUEST_FEATURES:
+ return "CLOCK_REQUEST_FEATURES";
+ case CSR_PSKEY_TRANSMIT_OFFSET_CLASS1:
+ return "TRANSMIT_OFFSET_CLASS1";
+ case CSR_PSKEY_TX_AVOID_PA_CLASS1_PIO:
+ return "TX_AVOID_PA_CLASS1_PIO";
+ case CSR_PSKEY_MR_PIO_CONFIG:
+ return "MR_PIO_CONFIG";
+ case CSR_PSKEY_UART_CONFIG2:
+ return "UART_CONFIG2";
+ case CSR_PSKEY_CLASS1_IQ_LVL:
+ return "CLASS1_IQ_LVL";
+ case CSR_PSKEY_CLASS1_TX_CONFIG2:
+ return "CLASS1_TX_CONFIG2";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1:
+ return "TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1:
+ return "TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR:
+ return "TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER:
+ return "TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD:
+ return "TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD";
+ case CSR_PSKEY_RX_MR_EQ_TAPS:
+ return "RX_MR_EQ_TAPS";
+ case CSR_PSKEY_TX_PRE_LVL_CLASS1:
+ return "TX_PRE_LVL_CLASS1";
+ case CSR_PSKEY_ANALOGUE_ATTENUATOR:
+ return "ANALOGUE_ATTENUATOR";
+ case CSR_PSKEY_MR_RX_FILTER_TRIM:
+ return "MR_RX_FILTER_TRIM";
+ case CSR_PSKEY_MR_RX_FILTER_RESPONSE:
+ return "MR_RX_FILTER_RESPONSE";
+ case CSR_PSKEY_PIO_WAKEUP_STATE:
+ return "PIO_WAKEUP_STATE";
+ case CSR_PSKEY_MR_TX_IF_ATTEN_OFF_TEMP:
+ return "MR_TX_IF_ATTEN_OFF_TEMP";
+ case CSR_PSKEY_LO_DIV_LATCH_BYPASS:
+ return "LO_DIV_LATCH_BYPASS";
+ case CSR_PSKEY_LO_VCO_STANDBY:
+ return "LO_VCO_STANDBY";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_SHIFT:
+ return "SLOW_CLOCK_FILTER_SHIFT";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_DIVIDER:
+ return "SLOW_CLOCK_FILTER_DIVIDER";
+ case CSR_PSKEY_USB_ATTRIBUTES_POWER:
+ return "USB_ATTRIBUTES_POWER";
+ case CSR_PSKEY_USB_ATTRIBUTES_WAKEUP:
+ return "USB_ATTRIBUTES_WAKEUP";
+ case CSR_PSKEY_DFU_ATTRIBUTES_MANIFESTATION_TOLERANT:
+ return "DFU_ATTRIBUTES_MANIFESTATION_TOLERANT";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_UPLOAD:
+ return "DFU_ATTRIBUTES_CAN_UPLOAD";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_DOWNLOAD:
+ return "DFU_ATTRIBUTES_CAN_DOWNLOAD";
+ case CSR_PSKEY_UART_CONFIG_STOP_BITS:
+ return "UART_CONFIG_STOP_BITS";
+ case CSR_PSKEY_UART_CONFIG_PARITY_BIT:
+ return "UART_CONFIG_PARITY_BIT";
+ case CSR_PSKEY_UART_CONFIG_FLOW_CTRL_EN:
+ return "UART_CONFIG_FLOW_CTRL_EN";
+ case CSR_PSKEY_UART_CONFIG_RTS_AUTO_EN:
+ return "UART_CONFIG_RTS_AUTO_EN";
+ case CSR_PSKEY_UART_CONFIG_RTS:
+ return "UART_CONFIG_RTS";
+ case CSR_PSKEY_UART_CONFIG_TX_ZERO_EN:
+ return "UART_CONFIG_TX_ZERO_EN";
+ case CSR_PSKEY_UART_CONFIG_NON_BCSP_EN:
+ return "UART_CONFIG_NON_BCSP_EN";
+ case CSR_PSKEY_UART_CONFIG_RX_RATE_DELAY:
+ return "UART_CONFIG_RX_RATE_DELAY";
+ case CSR_PSKEY_UART_SEQ_TIMEOUT:
+ return "UART_SEQ_TIMEOUT";
+ case CSR_PSKEY_UART_SEQ_RETRIES:
+ return "UART_SEQ_RETRIES";
+ case CSR_PSKEY_UART_SEQ_WINSIZE:
+ return "UART_SEQ_WINSIZE";
+ case CSR_PSKEY_UART_USE_CRC_ON_TX:
+ return "UART_USE_CRC_ON_TX";
+ case CSR_PSKEY_UART_HOST_INITIAL_STATE:
+ return "UART_HOST_INITIAL_STATE";
+ case CSR_PSKEY_UART_HOST_ATTENTION_SPAN:
+ return "UART_HOST_ATTENTION_SPAN";
+ case CSR_PSKEY_UART_HOST_WAKEUP_TIME:
+ return "UART_HOST_WAKEUP_TIME";
+ case CSR_PSKEY_UART_HOST_WAKEUP_WAIT:
+ return "UART_HOST_WAKEUP_WAIT";
+ case CSR_PSKEY_BCSP_LM_MODE:
+ return "BCSP_LM_MODE";
+ case CSR_PSKEY_BCSP_LM_SYNC_RETRIES:
+ return "BCSP_LM_SYNC_RETRIES";
+ case CSR_PSKEY_BCSP_LM_TSHY:
+ return "BCSP_LM_TSHY";
+ case CSR_PSKEY_UART_DFU_CONFIG_STOP_BITS:
+ return "UART_DFU_CONFIG_STOP_BITS";
+ case CSR_PSKEY_UART_DFU_CONFIG_PARITY_BIT:
+ return "UART_DFU_CONFIG_PARITY_BIT";
+ case CSR_PSKEY_UART_DFU_CONFIG_FLOW_CTRL_EN:
+ return "UART_DFU_CONFIG_FLOW_CTRL_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS_AUTO_EN:
+ return "UART_DFU_CONFIG_RTS_AUTO_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS:
+ return "UART_DFU_CONFIG_RTS";
+ case CSR_PSKEY_UART_DFU_CONFIG_TX_ZERO_EN:
+ return "UART_DFU_CONFIG_TX_ZERO_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_NON_BCSP_EN:
+ return "UART_DFU_CONFIG_NON_BCSP_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_RX_RATE_DELAY:
+ return "UART_DFU_CONFIG_RX_RATE_DELAY";
+ case CSR_PSKEY_AMUX_AIO0:
+ return "AMUX_AIO0";
+ case CSR_PSKEY_AMUX_AIO1:
+ return "AMUX_AIO1";
+ case CSR_PSKEY_AMUX_AIO2:
+ return "AMUX_AIO2";
+ case CSR_PSKEY_AMUX_AIO3:
+ return "AMUX_AIO3";
+ case CSR_PSKEY_LOCAL_NAME_SIMPLIFIED:
+ return "LOCAL_NAME_SIMPLIFIED";
+ case CSR_PSKEY_EXTENDED_STUB:
+ return "EXTENDED_STUB";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int csr_write_varid_valueless(int dd, uint16_t seqnum, uint16_t varid)
+{
+ unsigned char cmd[] = { 0x02, 0x00, 0x09, 0x00,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ switch (varid) {
+ case CSR_VARID_COLD_RESET:
+ case CSR_VARID_WARM_RESET:
+ case CSR_VARID_COLD_HALT:
+ case CSR_VARID_WARM_HALT:
+ return hci_send_cmd(dd, OGF_VENDOR_CMD, 0x00, sizeof(cmd) + 1, cp);
+ }
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int csr_write_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x02, 0x00, ((length / 2) + 5) & 0xff, ((length / 2) + 5) >> 8,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+ memcpy(cp + 11, value, length);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int csr_read_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x00, 0x00, ((length / 2) + 5) & 0xff, ((length / 2) + 5) >> 8,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+ memcpy(cp + 11, value, length);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ memcpy(value, rp + 11, length);
+
+ return 0;
+}
+
+int csr_read_varid_uint16(int dd, uint16_t seqnum, uint16_t varid, uint16_t *value)
+{
+ unsigned char cmd[] = { 0x00, 0x00, 0x09, 0x00,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ *value = rp[11] + (rp[12] << 8);
+
+ return 0;
+}
+
+int csr_read_varid_uint32(int dd, uint16_t seqnum, uint16_t varid, uint32_t *value)
+{
+ unsigned char cmd[] = { 0x00, 0x00, 0x09, 0x00,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ *value = ((rp[11] + (rp[12] << 8)) << 16) + (rp[13] + (rp[14] << 8));
+
+ return 0;
+}
+
+int csr_read_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x00, 0x00, ((length / 2) + 8) & 0xff, ((length / 2) + 8) >> 8,
+ seqnum & 0xff, seqnum >> 8, 0x03, 0x70, 0x00, 0x00,
+ pskey & 0xff, pskey >> 8,
+ (length / 2) & 0xff, (length / 2) >> 8,
+ stores & 0xff, stores >> 8, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length - 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ memcpy(value, rp + 17, length);
+
+ return 0;
+}
+
+int csr_write_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x02, 0x00, ((length / 2) + 8) & 0xff, ((length / 2) + 8) >> 8,
+ seqnum & 0xff, seqnum >> 8, 0x03, 0x70, 0x00, 0x00,
+ pskey & 0xff, pskey >> 8,
+ (length / 2) & 0xff, (length / 2) >> 8,
+ stores & 0xff, stores >> 8, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memcpy(cp + 17, value, length);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length - 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int csr_read_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t *value)
+{
+ uint8_t array[2] = { 0x00, 0x00 };
+ int err;
+
+ err = csr_read_pskey_complex(dd, seqnum, pskey, stores, array, 2);
+
+ *value = array[0] + (array[1] << 8);
+
+ return err;
+}
+
+int csr_write_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t value)
+{
+ uint8_t array[2] = { value & 0xff, value >> 8 };
+
+ return csr_write_pskey_complex(dd, seqnum, pskey, stores, array, 2);
+}
+
+int csr_read_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t *value)
+{
+ uint8_t array[4] = { 0x00, 0x00, 0x00, 0x00 };
+ int err;
+
+ err = csr_read_pskey_complex(dd, seqnum, pskey, stores, array, 4);
+
+ *value = ((array[0] + (array[1] << 8)) << 16) +
+ (array[2] + (array[3] << 8));
+
+ return err;
+}
+
+int csr_write_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t value)
+{
+ uint8_t array[4] = { (value & 0xff0000) >> 16, value >> 24,
+ value & 0xff, (value & 0xff00) >> 8 };
+
+ return csr_write_pskey_complex(dd, seqnum, pskey, stores, array, 4);
+}
+
+int psr_put(uint16_t pskey, uint8_t *value, uint16_t size)
+{
+ struct psr_data *item;
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ return -ENOMEM;
+
+ item->pskey = pskey;
+
+ if (size > 0) {
+ item->value = malloc(size);
+ if (!item->value) {
+ free(item);
+ return -ENOMEM;
+ }
+
+ memcpy(item->value, value, size);
+ item->size = size;
+ } else {
+ item->value = NULL;
+ item->size = 0;
+ }
+
+ item->next = NULL;
+
+ if (!head)
+ head = item;
+ else
+ tail->next = item;
+
+ tail = item;
+
+ return 0;
+}
+
+int psr_get(uint16_t *pskey, uint8_t *value, uint16_t *size)
+{
+ struct psr_data *item = head;
+
+ if (!head)
+ return -ENOENT;
+
+ *pskey = item->pskey;
+
+ if (item->value) {
+ if (value && item->size > 0)
+ memcpy(value, item->value, item->size);
+ free(item->value);
+ *size = item->size;
+ } else
+ *size = 0;
+
+ if (head == tail)
+ tail = NULL;
+
+ head = head->next;
+ free(item);
+
+ return 0;
+}
+
+static int parse_line(char *str)
+{
+ uint8_t array[256];
+ uint16_t value, pskey, length = 0;
+ char *off, *end;
+
+ pskey = strtol(str + 1, NULL, 16);
+ off = strstr(str, "=") + 1;
+ if (!off)
+ return -EIO;
+
+ while (1) {
+ value = strtol(off, &end, 16);
+ if (value == 0 && off == end)
+ break;
+
+ array[length++] = value & 0xff;
+ array[length++] = value >> 8;
+
+ if (*end == '\0')
+ break;
+
+ off = end + 1;
+ }
+
+ return psr_put(pskey, array, length);
+}
+
+int psr_read(const char *filename)
+{
+ struct stat st;
+ char *str, *map, *off, *end;
+ int fd, err = 0;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ if (fstat(fd, &st) < 0) {
+ err = -errno;
+ goto close;
+ }
+
+ map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!map || map == MAP_FAILED) {
+ err = -errno;
+ goto close;
+ }
+
+ off = map;
+
+ while (1) {
+ if (*off == '\r' || *off == '\n') {
+ off++;
+ continue;
+ }
+
+ end = strpbrk(off, "\r\n");
+ if (!end)
+ break;
+
+ str = malloc(end - off + 1);
+ if (!str)
+ break;
+
+ memset(str, 0, end - off + 1);
+ strncpy(str, off, end - off);
+ if (*str == '&')
+ parse_line(str);
+
+ free(str);
+ off = end + 1;
+ }
+
+ munmap(map, st.st_size);
+
+close:
+ close(fd);
+
+ return err;
+}
+
+int psr_print(void)
+{
+ uint8_t array[256];
+ uint16_t pskey, length;
+ char *str, val[7];
+ int i;
+
+ while (1) {
+ if (psr_get(&pskey, array, &length) < 0)
+ break;
+
+ str = csr_pskeytoval(pskey);
+ if (!strcasecmp(str, "UNKNOWN")) {
+ sprintf(val, "0x%04x", pskey);
+ str = NULL;
+ }
+
+ printf("// %s%s\n&%04x =", str ? "PSKEY_" : "",
+ str ? str : val, pskey);
+ for (i = 0; i < length / 2; i++)
+ printf(" %02x%02x", array[i * 2 + 1], array[i * 2]);
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/csr.h b/external/cache/sources/hcitools/csr.h
new file mode 100644
index 0000000..8b94d7b
--- /dev/null
+++ b/external/cache/sources/hcitools/csr.h
@@ -0,0 +1,553 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include
+#include
+
+#define CSR_VARID_PS_CLR_ALL 0x000b /* valueless */
+#define CSR_VARID_PS_FACTORY_SET 0x000c /* valueless */
+#define CSR_VARID_PS_CLR_ALL_STORES 0x082d /* uint16 */
+#define CSR_VARID_BC01_STATUS 0x2801 /* uint16 */
+#define CSR_VARID_BUILDID 0x2819 /* uint16 */
+#define CSR_VARID_CHIPVER 0x281a /* uint16 */
+#define CSR_VARID_CHIPREV 0x281b /* uint16 */
+#define CSR_VARID_INTERFACE_VERSION 0x2825 /* uint16 */
+#define CSR_VARID_RAND 0x282a /* uint16 */
+#define CSR_VARID_MAX_CRYPT_KEY_LENGTH 0x282c /* uint16 */
+#define CSR_VARID_CHIPANAREV 0x2836 /* uint16 */
+#define CSR_VARID_BUILDID_LOADER 0x2838 /* uint16 */
+#define CSR_VARID_BT_CLOCK 0x2c00 /* uint32 */
+#define CSR_VARID_PS_NEXT 0x3005 /* complex */
+#define CSR_VARID_PS_SIZE 0x3006 /* complex */
+#define CSR_VARID_CRYPT_KEY_LENGTH 0x3008 /* complex */
+#define CSR_VARID_PICONET_INSTANCE 0x3009 /* complex */
+#define CSR_VARID_GET_CLR_EVT 0x300a /* complex */
+#define CSR_VARID_GET_NEXT_BUILDDEF 0x300b /* complex */
+#define CSR_VARID_PS_MEMORY_TYPE 0x3012 /* complex */
+#define CSR_VARID_READ_BUILD_NAME 0x301c /* complex */
+#define CSR_VARID_COLD_RESET 0x4001 /* valueless */
+#define CSR_VARID_WARM_RESET 0x4002 /* valueless */
+#define CSR_VARID_COLD_HALT 0x4003 /* valueless */
+#define CSR_VARID_WARM_HALT 0x4004 /* valueless */
+#define CSR_VARID_INIT_BT_STACK 0x4005 /* valueless */
+#define CSR_VARID_ACTIVATE_BT_STACK 0x4006 /* valueless */
+#define CSR_VARID_ENABLE_TX 0x4007 /* valueless */
+#define CSR_VARID_DISABLE_TX 0x4008 /* valueless */
+#define CSR_VARID_RECAL 0x4009 /* valueless */
+#define CSR_VARID_PS_FACTORY_RESTORE 0x400d /* valueless */
+#define CSR_VARID_PS_FACTORY_RESTORE_ALL 0x400e /* valueless */
+#define CSR_VARID_PS_DEFRAG_RESET 0x400f /* valueless */
+#define CSR_VARID_KILL_VM_APPLICATION 0x4010 /* valueless */
+#define CSR_VARID_HOPPING_ON 0x4011 /* valueless */
+#define CSR_VARID_CANCEL_PAGE 0x4012 /* valueless */
+#define CSR_VARID_PS_CLR 0x4818 /* uint16 */
+#define CSR_VARID_MAP_SCO_PCM 0x481c /* uint16 */
+#define CSR_VARID_SINGLE_CHAN 0x482e /* uint16 */
+#define CSR_VARID_RADIOTEST 0x5004 /* complex */
+#define CSR_VARID_PS_CLR_STORES 0x500c /* complex */
+#define CSR_VARID_NO_VARIABLE 0x6000 /* valueless */
+#define CSR_VARID_CONFIG_UART 0x6802 /* uint16 */
+#define CSR_VARID_PANIC_ARG 0x6805 /* uint16 */
+#define CSR_VARID_FAULT_ARG 0x6806 /* uint16 */
+#define CSR_VARID_MAX_TX_POWER 0x6827 /* int8 */
+#define CSR_VARID_DEFAULT_TX_POWER 0x682b /* int8 */
+#define CSR_VARID_PS 0x7003 /* complex */
+
+#define CSR_PSKEY_BDADDR 0x0001 /* bdaddr / uint16[] = { 0x00A5A5, 0x5b, 0x0002 } */
+#define CSR_PSKEY_COUNTRYCODE 0x0002 /* uint16 */
+#define CSR_PSKEY_CLASSOFDEVICE 0x0003 /* bdcod */
+#define CSR_PSKEY_DEVICE_DRIFT 0x0004 /* uint16 */
+#define CSR_PSKEY_DEVICE_JITTER 0x0005 /* uint16 */
+#define CSR_PSKEY_MAX_ACLS 0x000d /* uint16 */
+#define CSR_PSKEY_MAX_SCOS 0x000e /* uint16 */
+#define CSR_PSKEY_MAX_REMOTE_MASTERS 0x000f /* uint16 */
+#define CSR_PSKEY_ENABLE_MASTERY_WITH_SLAVERY 0x0010 /* bool */
+#define CSR_PSKEY_H_HC_FC_MAX_ACL_PKT_LEN 0x0011 /* uint16 */
+#define CSR_PSKEY_H_HC_FC_MAX_SCO_PKT_LEN 0x0012 /* uint8 */
+#define CSR_PSKEY_H_HC_FC_MAX_ACL_PKTS 0x0013 /* uint16 */
+#define CSR_PSKEY_H_HC_FC_MAX_SCO_PKTS 0x0014 /* uint16 */
+#define CSR_PSKEY_LC_FC_BUFFER_LOW_WATER_MARK 0x0015 /* lc_fc_lwm */
+#define CSR_PSKEY_LC_MAX_TX_POWER 0x0017 /* int16 */
+#define CSR_PSKEY_TX_GAIN_RAMP 0x001d /* uint16 */
+#define CSR_PSKEY_LC_POWER_TABLE 0x001e /* power_setting[] */
+#define CSR_PSKEY_LC_PEER_POWER_PERIOD 0x001f /* TIME */
+#define CSR_PSKEY_LC_FC_POOLS_LOW_WATER_MARK 0x0020 /* lc_fc_lwm */
+#define CSR_PSKEY_LC_DEFAULT_TX_POWER 0x0021 /* int16 */
+#define CSR_PSKEY_LC_RSSI_GOLDEN_RANGE 0x0022 /* uint8 */
+#define CSR_PSKEY_LC_COMBO_DISABLE_PIO_MASK 0x0028 /* uint16[] */
+#define CSR_PSKEY_LC_COMBO_PRIORITY_PIO_MASK 0x0029 /* uint16[] */
+#define CSR_PSKEY_LC_COMBO_DOT11_CHANNEL_PIO_BASE 0x002a /* uint16 */
+#define CSR_PSKEY_LC_COMBO_DOT11_BLOCK_CHANNELS 0x002b /* uint16 */
+#define CSR_PSKEY_LC_MAX_TX_POWER_NO_RSSI 0x002d /* int8 */
+#define CSR_PSKEY_LC_CONNECTION_RX_WINDOW 0x002e /* uint16 */
+#define CSR_PSKEY_LC_COMBO_DOT11_TX_PROTECTION_MODE 0x0030 /* uint16 */
+#define CSR_PSKEY_LC_ENHANCED_POWER_TABLE 0x0031 /* enhanced_power_setting[] */
+#define CSR_PSKEY_LC_WIDEBAND_RSSI_CONFIG 0x0032 /* wideband_rssi_config */
+#define CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_LEAD 0x0033 /* uint16 */
+#define CSR_PSKEY_BT_CLOCK_INIT 0x0034 /* uint32 */
+#define CSR_PSKEY_TX_MR_MOD_DELAY 0x0038 /* uint8 */
+#define CSR_PSKEY_RX_MR_SYNC_TIMING 0x0039 /* uint16 */
+#define CSR_PSKEY_RX_MR_SYNC_CONFIG 0x003a /* uint16 */
+#define CSR_PSKEY_LC_LOST_SYNC_SLOTS 0x003b /* uint16 */
+#define CSR_PSKEY_RX_MR_SAMP_CONFIG 0x003c /* uint16 */
+#define CSR_PSKEY_AGC_HYST_LEVELS 0x003d /* agc_hyst_config */
+#define CSR_PSKEY_RX_LEVEL_LOW_SIGNAL 0x003e /* uint16 */
+#define CSR_PSKEY_AGC_IQ_LVL_VALUES 0x003f /* IQ_LVL_VAL[] */
+#define CSR_PSKEY_MR_FTRIM_OFFSET_12DB 0x0040 /* uint16 */
+#define CSR_PSKEY_MR_FTRIM_OFFSET_6DB 0x0041 /* uint16 */
+#define CSR_PSKEY_NO_CAL_ON_BOOT 0x0042 /* bool */
+#define CSR_PSKEY_RSSI_HI_TARGET 0x0043 /* uint8 */
+#define CSR_PSKEY_PREFERRED_MIN_ATTENUATION 0x0044 /* uint8 */
+#define CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_OVERRIDE 0x0045 /* bool */
+#define CSR_PSKEY_LC_MULTISLOT_HOLDOFF 0x0047 /* TIME */
+#define CSR_PSKEY_FREE_KEY_PIGEON_HOLE 0x00c9 /* uint16 */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR0 0x00ca /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR1 0x00cb /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR2 0x00cc /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR3 0x00cd /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR4 0x00ce /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR5 0x00cf /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR6 0x00d0 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR7 0x00d1 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR8 0x00d2 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR9 0x00d3 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR10 0x00d4 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR11 0x00d5 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR12 0x00d6 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR13 0x00d7 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR14 0x00d8 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR15 0x00d9 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_ENC_KEY_LMIN 0x00da /* uint16 */
+#define CSR_PSKEY_ENC_KEY_LMAX 0x00db /* uint16 */
+#define CSR_PSKEY_LOCAL_SUPPORTED_FEATURES 0x00ef /* uint16[] = { 0xffff, 0xfe8f, 0xf99b, 0x8000 }*/
+#define CSR_PSKEY_LM_USE_UNIT_KEY 0x00f0 /* bool */
+#define CSR_PSKEY_HCI_NOP_DISABLE 0x00f2 /* bool */
+#define CSR_PSKEY_LM_MAX_EVENT_FILTERS 0x00f4 /* uint8 */
+#define CSR_PSKEY_LM_USE_ENC_MODE_BROADCAST 0x00f5 /* bool */
+#define CSR_PSKEY_LM_TEST_SEND_ACCEPTED_TWICE 0x00f6 /* bool */
+#define CSR_PSKEY_LM_MAX_PAGE_HOLD_TIME 0x00f7 /* uint16 */
+#define CSR_PSKEY_AFH_ADAPTATION_RESPONSE_TIME 0x00f8 /* uint16 */
+#define CSR_PSKEY_AFH_OPTIONS 0x00f9 /* uint16 */
+#define CSR_PSKEY_AFH_RSSI_RUN_PERIOD 0x00fa /* uint16 */
+#define CSR_PSKEY_AFH_REENABLE_CHANNEL_TIME 0x00fb /* uint16 */
+#define CSR_PSKEY_NO_DROP_ON_ACR_MS_FAIL 0x00fc /* bool */
+#define CSR_PSKEY_MAX_PRIVATE_KEYS 0x00fd /* uint8 */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR0 0x00fe /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR1 0x00ff /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR2 0x0100 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR3 0x0101 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR4 0x0102 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR5 0x0103 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR6 0x0104 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR7 0x0105 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS 0x0106 /* uint16[] = { 0xffff, 0x03ff, 0xfffe, 0xffff, 0xffff, 0xffff, 0x0ff3, 0xfff8, 0x003f } */
+#define CSR_PSKEY_LM_MAX_ABSENCE_INDEX 0x0107 /* uint8 */
+#define CSR_PSKEY_DEVICE_NAME 0x0108 /* uint16[] */
+#define CSR_PSKEY_AFH_RSSI_THRESHOLD 0x0109 /* uint16 */
+#define CSR_PSKEY_LM_CASUAL_SCAN_INTERVAL 0x010a /* uint16 */
+#define CSR_PSKEY_AFH_MIN_MAP_CHANGE 0x010b /* uint16[] */
+#define CSR_PSKEY_AFH_RSSI_LP_RUN_PERIOD 0x010c /* uint16 */
+#define CSR_PSKEY_HCI_LMP_LOCAL_VERSION 0x010d /* uint16 */
+#define CSR_PSKEY_LMP_REMOTE_VERSION 0x010e /* uint8 */
+#define CSR_PSKEY_HOLD_ERROR_MESSAGE_NUMBER 0x0113 /* uint16 */
+#define CSR_PSKEY_DFU_ATTRIBUTES 0x0136 /* uint8 */
+#define CSR_PSKEY_DFU_DETACH_TO 0x0137 /* uint16 */
+#define CSR_PSKEY_DFU_TRANSFER_SIZE 0x0138 /* uint16 */
+#define CSR_PSKEY_DFU_ENABLE 0x0139 /* bool */
+#define CSR_PSKEY_DFU_LIN_REG_ENABLE 0x013a /* bool */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_MSB 0x015e /* uint16[] */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_LSB 0x015f /* uint16[] */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_M_DASH 0x0160 /* uint16 */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_R2N_MSB 0x0161 /* uint16[] */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_R2N_LSB 0x0162 /* uint16[] */
+#define CSR_PSKEY_BCSP_LM_PS_BLOCK 0x0192 /* BCSP_LM_PS_BLOCK */
+#define CSR_PSKEY_HOSTIO_FC_PS_BLOCK 0x0193 /* HOSTIO_FC_PS_BLOCK */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO0 0x0194 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO1 0x0195 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO2 0x0196 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO3 0x0197 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO4 0x0198 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO5 0x0199 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO6 0x019a /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO7 0x019b /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO8 0x019c /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO9 0x019d /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO10 0x019e /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO11 0x019f /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO12 0x01a0 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO13 0x01a1 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO14 0x01a2 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO15 0x01a3 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_UART_RESET_TIMEOUT 0x01a4 /* TIME */
+#define CSR_PSKEY_HOSTIO_USE_HCI_EXTN 0x01a5 /* bool */
+#define CSR_PSKEY_HOSTIO_USE_HCI_EXTN_CCFC 0x01a6 /* bool */
+#define CSR_PSKEY_HOSTIO_HCI_EXTN_PAYLOAD_SIZE 0x01a7 /* uint16 */
+#define CSR_PSKEY_BCSP_LM_CNF_CNT_LIMIT 0x01aa /* uint16 */
+#define CSR_PSKEY_HOSTIO_MAP_SCO_PCM 0x01ab /* bool */
+#define CSR_PSKEY_HOSTIO_AWKWARD_PCM_SYNC 0x01ac /* bool */
+#define CSR_PSKEY_HOSTIO_BREAK_POLL_PERIOD 0x01ad /* TIME */
+#define CSR_PSKEY_HOSTIO_MIN_UART_HCI_SCO_SIZE 0x01ae /* uint16 */
+#define CSR_PSKEY_HOSTIO_MAP_SCO_CODEC 0x01b0 /* bool */
+#define CSR_PSKEY_PCM_CVSD_TX_HI_FREQ_BOOST 0x01b1 /* uint16 */
+#define CSR_PSKEY_PCM_CVSD_RX_HI_FREQ_BOOST 0x01b2 /* uint16 */
+#define CSR_PSKEY_PCM_CONFIG32 0x01b3 /* uint32 */
+#define CSR_PSKEY_USE_OLD_BCSP_LE 0x01b4 /* uint16 */
+#define CSR_PSKEY_PCM_CVSD_USE_NEW_FILTER 0x01b5 /* bool */
+#define CSR_PSKEY_PCM_FORMAT 0x01b6 /* uint16 */
+#define CSR_PSKEY_CODEC_OUT_GAIN 0x01b7 /* uint16 */
+#define CSR_PSKEY_CODEC_IN_GAIN 0x01b8 /* uint16 */
+#define CSR_PSKEY_CODEC_PIO 0x01b9 /* uint16 */
+#define CSR_PSKEY_PCM_LOW_JITTER_CONFIG 0x01ba /* uint32 */
+#define CSR_PSKEY_HOSTIO_SCO_PCM_THRESHOLDS 0x01bb /* uint16[] */
+#define CSR_PSKEY_HOSTIO_SCO_HCI_THRESHOLDS 0x01bc /* uint16[] */
+#define CSR_PSKEY_HOSTIO_MAP_SCO_PCM_SLOT 0x01bd /* uint16 */
+#define CSR_PSKEY_UART_BAUDRATE 0x01be /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_BCSP 0x01bf /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_H4 0x01c0 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_H5 0x01c1 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_USR 0x01c2 /* uint16 */
+#define CSR_PSKEY_UART_TX_CRCS 0x01c3 /* bool */
+#define CSR_PSKEY_UART_ACK_TIMEOUT 0x01c4 /* uint16 */
+#define CSR_PSKEY_UART_TX_MAX_ATTEMPTS 0x01c5 /* uint16 */
+#define CSR_PSKEY_UART_TX_WINDOW_SIZE 0x01c6 /* uint16 */
+#define CSR_PSKEY_UART_HOST_WAKE 0x01c7 /* uint16[] */
+#define CSR_PSKEY_HOSTIO_THROTTLE_TIMEOUT 0x01c8 /* TIME */
+#define CSR_PSKEY_PCM_ALWAYS_ENABLE 0x01c9 /* bool */
+#define CSR_PSKEY_UART_HOST_WAKE_SIGNAL 0x01ca /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_H4DS 0x01cb /* uint16 */
+#define CSR_PSKEY_H4DS_WAKE_DURATION 0x01cc /* uint16 */
+#define CSR_PSKEY_H4DS_MAXWU 0x01cd /* uint16 */
+#define CSR_PSKEY_H4DS_LE_TIMER_PERIOD 0x01cf /* uint16 */
+#define CSR_PSKEY_H4DS_TWU_TIMER_PERIOD 0x01d0 /* uint16 */
+#define CSR_PSKEY_H4DS_UART_IDLE_TIMER_PERIOD 0x01d1 /* uint16 */
+#define CSR_PSKEY_ANA_FTRIM 0x01f6 /* uint16 */
+#define CSR_PSKEY_WD_TIMEOUT 0x01f7 /* TIME */
+#define CSR_PSKEY_WD_PERIOD 0x01f8 /* TIME */
+#define CSR_PSKEY_HOST_INTERFACE 0x01f9 /* phys_bus */
+#define CSR_PSKEY_HQ_HOST_TIMEOUT 0x01fb /* TIME */
+#define CSR_PSKEY_HQ_ACTIVE 0x01fc /* bool */
+#define CSR_PSKEY_BCCMD_SECURITY_ACTIVE 0x01fd /* bool */
+#define CSR_PSKEY_ANA_FREQ 0x01fe /* uint16 */
+#define CSR_PSKEY_PIO_PROTECT_MASK 0x0202 /* uint16 */
+#define CSR_PSKEY_PMALLOC_SIZES 0x0203 /* uint16[] */
+#define CSR_PSKEY_UART_BAUD_RATE 0x0204 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG 0x0205 /* uint16 */
+#define CSR_PSKEY_STUB 0x0207 /* uint16 */
+#define CSR_PSKEY_TXRX_PIO_CONTROL 0x0209 /* uint16 */
+#define CSR_PSKEY_ANA_RX_LEVEL 0x020b /* uint16 */
+#define CSR_PSKEY_ANA_RX_FTRIM 0x020c /* uint16 */
+#define CSR_PSKEY_PSBC_DATA_VERSION 0x020d /* uint16 */
+#define CSR_PSKEY_PCM0_ATTENUATION 0x020f /* uint16 */
+#define CSR_PSKEY_LO_LVL_MAX 0x0211 /* uint16 */
+#define CSR_PSKEY_LO_ADC_AMPL_MIN 0x0212 /* uint16 */
+#define CSR_PSKEY_LO_ADC_AMPL_MAX 0x0213 /* uint16 */
+#define CSR_PSKEY_IQ_TRIM_CHANNEL 0x0214 /* uint16 */
+#define CSR_PSKEY_IQ_TRIM_GAIN 0x0215 /* uint16 */
+#define CSR_PSKEY_IQ_TRIM_ENABLE 0x0216 /* iq_trim_enable_flag */
+#define CSR_PSKEY_TX_OFFSET_HALF_MHZ 0x0217 /* int16 */
+#define CSR_PSKEY_GBL_MISC_ENABLES 0x0221 /* uint16 */
+#define CSR_PSKEY_UART_SLEEP_TIMEOUT 0x0222 /* uint16 */
+#define CSR_PSKEY_DEEP_SLEEP_STATE 0x0229 /* deep_sleep_state */
+#define CSR_PSKEY_IQ_ENABLE_PHASE_TRIM 0x022d /* bool */
+#define CSR_PSKEY_HCI_HANDLE_FREEZE_PERIOD 0x0237 /* TIME */
+#define CSR_PSKEY_MAX_FROZEN_HCI_HANDLES 0x0238 /* uint16 */
+#define CSR_PSKEY_PAGETABLE_DESTRUCTION_DELAY 0x0239 /* TIME */
+#define CSR_PSKEY_IQ_TRIM_PIO_SETTINGS 0x023a /* uint8 */
+#define CSR_PSKEY_USE_EXTERNAL_CLOCK 0x023b /* bool */
+#define CSR_PSKEY_DEEP_SLEEP_WAKE_CTS 0x023c /* uint16 */
+#define CSR_PSKEY_FC_HC2H_FLUSH_DELAY 0x023d /* TIME */
+#define CSR_PSKEY_RX_HIGHSIDE 0x023e /* bool */
+#define CSR_PSKEY_TX_PRE_LVL 0x0240 /* uint8 */
+#define CSR_PSKEY_RX_SINGLE_ENDED 0x0242 /* bool */
+#define CSR_PSKEY_TX_FILTER_CONFIG 0x0243 /* uint32 */
+#define CSR_PSKEY_CLOCK_REQUEST_ENABLE 0x0246 /* uint16 */
+#define CSR_PSKEY_RX_MIN_ATTEN 0x0249 /* uint16 */
+#define CSR_PSKEY_XTAL_TARGET_AMPLITUDE 0x024b /* uint8 */
+#define CSR_PSKEY_PCM_MIN_CPU_CLOCK 0x024d /* uint16 */
+#define CSR_PSKEY_HOST_INTERFACE_PIO_USB 0x0250 /* uint16 */
+#define CSR_PSKEY_CPU_IDLE_MODE 0x0251 /* cpu_idle_mode */
+#define CSR_PSKEY_DEEP_SLEEP_CLEAR_RTS 0x0252 /* bool */
+#define CSR_PSKEY_RF_RESONANCE_TRIM 0x0254 /* uint16 */
+#define CSR_PSKEY_DEEP_SLEEP_PIO_WAKE 0x0255 /* uint16 */
+#define CSR_PSKEY_DRAIN_BORE_TIMERS 0x0256 /* uint32[] */
+#define CSR_PSKEY_DRAIN_TX_POWER_BASE 0x0257 /* uint16 */
+#define CSR_PSKEY_MODULE_ID 0x0259 /* uint32 */
+#define CSR_PSKEY_MODULE_DESIGN 0x025a /* uint16 */
+#define CSR_PSKEY_MODULE_SECURITY_CODE 0x025c /* uint16[] */
+#define CSR_PSKEY_VM_DISABLE 0x025d /* bool */
+#define CSR_PSKEY_MOD_MANUF0 0x025e /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF1 0x025f /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF2 0x0260 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF3 0x0261 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF4 0x0262 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF5 0x0263 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF6 0x0264 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF7 0x0265 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF8 0x0266 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF9 0x0267 /* uint16[] */
+#define CSR_PSKEY_DUT_VM_DISABLE 0x0268 /* bool */
+#define CSR_PSKEY_USR0 0x028a /* uint16[] */
+#define CSR_PSKEY_USR1 0x028b /* uint16[] */
+#define CSR_PSKEY_USR2 0x028c /* uint16[] */
+#define CSR_PSKEY_USR3 0x028d /* uint16[] */
+#define CSR_PSKEY_USR4 0x028e /* uint16[] */
+#define CSR_PSKEY_USR5 0x028f /* uint16[] */
+#define CSR_PSKEY_USR6 0x0290 /* uint16[] */
+#define CSR_PSKEY_USR7 0x0291 /* uint16[] */
+#define CSR_PSKEY_USR8 0x0292 /* uint16[] */
+#define CSR_PSKEY_USR9 0x0293 /* uint16[] */
+#define CSR_PSKEY_USR10 0x0294 /* uint16[] */
+#define CSR_PSKEY_USR11 0x0295 /* uint16[] */
+#define CSR_PSKEY_USR12 0x0296 /* uint16[] */
+#define CSR_PSKEY_USR13 0x0297 /* uint16[] */
+#define CSR_PSKEY_USR14 0x0298 /* uint16[] */
+#define CSR_PSKEY_USR15 0x0299 /* uint16[] */
+#define CSR_PSKEY_USR16 0x029a /* uint16[] */
+#define CSR_PSKEY_USR17 0x029b /* uint16[] */
+#define CSR_PSKEY_USR18 0x029c /* uint16[] */
+#define CSR_PSKEY_USR19 0x029d /* uint16[] */
+#define CSR_PSKEY_USR20 0x029e /* uint16[] */
+#define CSR_PSKEY_USR21 0x029f /* uint16[] */
+#define CSR_PSKEY_USR22 0x02a0 /* uint16[] */
+#define CSR_PSKEY_USR23 0x02a1 /* uint16[] */
+#define CSR_PSKEY_USR24 0x02a2 /* uint16[] */
+#define CSR_PSKEY_USR25 0x02a3 /* uint16[] */
+#define CSR_PSKEY_USR26 0x02a4 /* uint16[] */
+#define CSR_PSKEY_USR27 0x02a5 /* uint16[] */
+#define CSR_PSKEY_USR28 0x02a6 /* uint16[] */
+#define CSR_PSKEY_USR29 0x02a7 /* uint16[] */
+#define CSR_PSKEY_USR30 0x02a8 /* uint16[] */
+#define CSR_PSKEY_USR31 0x02a9 /* uint16[] */
+#define CSR_PSKEY_USR32 0x02aa /* uint16[] */
+#define CSR_PSKEY_USR33 0x02ab /* uint16[] */
+#define CSR_PSKEY_USR34 0x02ac /* uint16[] */
+#define CSR_PSKEY_USR35 0x02ad /* uint16[] */
+#define CSR_PSKEY_USR36 0x02ae /* uint16[] */
+#define CSR_PSKEY_USR37 0x02af /* uint16[] */
+#define CSR_PSKEY_USR38 0x02b0 /* uint16[] */
+#define CSR_PSKEY_USR39 0x02b1 /* uint16[] */
+#define CSR_PSKEY_USR40 0x02b2 /* uint16[] */
+#define CSR_PSKEY_USR41 0x02b3 /* uint16[] */
+#define CSR_PSKEY_USR42 0x02b4 /* uint16[] */
+#define CSR_PSKEY_USR43 0x02b5 /* uint16[] */
+#define CSR_PSKEY_USR44 0x02b6 /* uint16[] */
+#define CSR_PSKEY_USR45 0x02b7 /* uint16[] */
+#define CSR_PSKEY_USR46 0x02b8 /* uint16[] */
+#define CSR_PSKEY_USR47 0x02b9 /* uint16[] */
+#define CSR_PSKEY_USR48 0x02ba /* uint16[] */
+#define CSR_PSKEY_USR49 0x02bb /* uint16[] */
+#define CSR_PSKEY_USB_VERSION 0x02bc /* uint16 */
+#define CSR_PSKEY_USB_DEVICE_CLASS_CODES 0x02bd /* usbclass */
+#define CSR_PSKEY_USB_VENDOR_ID 0x02be /* uint16 */
+#define CSR_PSKEY_USB_PRODUCT_ID 0x02bf /* uint16 */
+#define CSR_PSKEY_USB_MANUF_STRING 0x02c1 /* unicodestring */
+#define CSR_PSKEY_USB_PRODUCT_STRING 0x02c2 /* unicodestring */
+#define CSR_PSKEY_USB_SERIAL_NUMBER_STRING 0x02c3 /* unicodestring */
+#define CSR_PSKEY_USB_CONFIG_STRING 0x02c4 /* unicodestring */
+#define CSR_PSKEY_USB_ATTRIBUTES 0x02c5 /* uint8 */
+#define CSR_PSKEY_USB_MAX_POWER 0x02c6 /* uint16 */
+#define CSR_PSKEY_USB_BT_IF_CLASS_CODES 0x02c7 /* usbclass */
+#define CSR_PSKEY_USB_LANGID 0x02c9 /* uint16 */
+#define CSR_PSKEY_USB_DFU_CLASS_CODES 0x02ca /* usbclass */
+#define CSR_PSKEY_USB_DFU_PRODUCT_ID 0x02cb /* uint16 */
+#define CSR_PSKEY_USB_PIO_DETACH 0x02ce /* uint16 */
+#define CSR_PSKEY_USB_PIO_WAKEUP 0x02cf /* uint16 */
+#define CSR_PSKEY_USB_PIO_PULLUP 0x02d0 /* uint16 */
+#define CSR_PSKEY_USB_PIO_VBUS 0x02d1 /* uint16 */
+#define CSR_PSKEY_USB_PIO_WAKE_TIMEOUT 0x02d2 /* uint16 */
+#define CSR_PSKEY_USB_PIO_RESUME 0x02d3 /* uint16 */
+#define CSR_PSKEY_USB_BT_SCO_IF_CLASS_CODES 0x02d4 /* usbclass */
+#define CSR_PSKEY_USB_SUSPEND_PIO_LEVEL 0x02d5 /* uint16 */
+#define CSR_PSKEY_USB_SUSPEND_PIO_DIR 0x02d6 /* uint16 */
+#define CSR_PSKEY_USB_SUSPEND_PIO_MASK 0x02d7 /* uint16 */
+#define CSR_PSKEY_USB_ENDPOINT_0_MAX_PACKET_SIZE 0x02d8 /* uint8 */
+#define CSR_PSKEY_USB_CONFIG 0x02d9 /* uint16 */
+#define CSR_PSKEY_RADIOTEST_ATTEN_INIT 0x0320 /* uint16 */
+#define CSR_PSKEY_RADIOTEST_FIRST_TRIM_TIME 0x0326 /* TIME */
+#define CSR_PSKEY_RADIOTEST_SUBSEQUENT_TRIM_TIME 0x0327 /* TIME */
+#define CSR_PSKEY_RADIOTEST_LO_LVL_TRIM_ENABLE 0x0328 /* bool */
+#define CSR_PSKEY_RADIOTEST_DISABLE_MODULATION 0x032c /* bool */
+#define CSR_PSKEY_RFCOMM_FCON_THRESHOLD 0x0352 /* uint16 */
+#define CSR_PSKEY_RFCOMM_FCOFF_THRESHOLD 0x0353 /* uint16 */
+#define CSR_PSKEY_IPV6_STATIC_ADDR 0x0354 /* uint16[] */
+#define CSR_PSKEY_IPV4_STATIC_ADDR 0x0355 /* uint32 */
+#define CSR_PSKEY_IPV6_STATIC_PREFIX_LEN 0x0356 /* uint8 */
+#define CSR_PSKEY_IPV6_STATIC_ROUTER_ADDR 0x0357 /* uint16[] */
+#define CSR_PSKEY_IPV4_STATIC_SUBNET_MASK 0x0358 /* uint32 */
+#define CSR_PSKEY_IPV4_STATIC_ROUTER_ADDR 0x0359 /* uint32 */
+#define CSR_PSKEY_MDNS_NAME 0x035a /* char[] */
+#define CSR_PSKEY_FIXED_PIN 0x035b /* uint8[] */
+#define CSR_PSKEY_MDNS_PORT 0x035c /* uint16 */
+#define CSR_PSKEY_MDNS_TTL 0x035d /* uint8 */
+#define CSR_PSKEY_MDNS_IPV4_ADDR 0x035e /* uint32 */
+#define CSR_PSKEY_ARP_CACHE_TIMEOUT 0x035f /* uint16 */
+#define CSR_PSKEY_HFP_POWER_TABLE 0x0360 /* uint16[] */
+#define CSR_PSKEY_DRAIN_BORE_TIMER_COUNTERS 0x03e7 /* uint32[] */
+#define CSR_PSKEY_DRAIN_BORE_COUNTERS 0x03e6 /* uint32[] */
+#define CSR_PSKEY_LOOP_FILTER_TRIM 0x03e4 /* uint16 */
+#define CSR_PSKEY_DRAIN_BORE_CURRENT_PEAK 0x03e3 /* uint32[] */
+#define CSR_PSKEY_VM_E2_CACHE_LIMIT 0x03e2 /* uint16 */
+#define CSR_PSKEY_FORCE_16MHZ_REF_PIO 0x03e1 /* uint16 */
+#define CSR_PSKEY_CDMA_LO_REF_LIMITS 0x03df /* uint16 */
+#define CSR_PSKEY_CDMA_LO_ERROR_LIMITS 0x03de /* uint16 */
+#define CSR_PSKEY_CLOCK_STARTUP_DELAY 0x03dd /* uint16 */
+#define CSR_PSKEY_DEEP_SLEEP_CORRECTION_FACTOR 0x03dc /* int16 */
+#define CSR_PSKEY_TEMPERATURE_CALIBRATION 0x03db /* temperature_calibration */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA 0x03da /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL 0x03d9 /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB 0x03d8 /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_ANA_FTRIM 0x03d7 /* temperature_calibration[] */
+#define CSR_PSKEY_TEST_DELTA_OFFSET 0x03d6 /* uint16 */
+#define CSR_PSKEY_RX_DYNAMIC_LVL_OFFSET 0x03d4 /* uint16 */
+#define CSR_PSKEY_TEST_FORCE_OFFSET 0x03d3 /* bool */
+#define CSR_PSKEY_RF_TRAP_BAD_DIVISION_RATIOS 0x03cf /* uint16 */
+#define CSR_PSKEY_RADIOTEST_CDMA_LO_REF_LIMITS 0x03ce /* uint16 */
+#define CSR_PSKEY_INITIAL_BOOTMODE 0x03cd /* int16 */
+#define CSR_PSKEY_ONCHIP_HCI_CLIENT 0x03cc /* bool */
+#define CSR_PSKEY_RX_ATTEN_BACKOFF 0x03ca /* uint16 */
+#define CSR_PSKEY_RX_ATTEN_UPDATE_RATE 0x03c9 /* uint16 */
+#define CSR_PSKEY_SYNTH_TXRX_THRESHOLDS 0x03c7 /* uint16 */
+#define CSR_PSKEY_MIN_WAIT_STATES 0x03c6 /* uint16 */
+#define CSR_PSKEY_RSSI_CORRECTION 0x03c5 /* int8 */
+#define CSR_PSKEY_SCHED_THROTTLE_TIMEOUT 0x03c4 /* TIME */
+#define CSR_PSKEY_DEEP_SLEEP_USE_EXTERNAL_CLOCK 0x03c3 /* bool */
+#define CSR_PSKEY_TRIM_RADIO_FILTERS 0x03c2 /* uint16 */
+#define CSR_PSKEY_TRANSMIT_OFFSET 0x03c1 /* int16 */
+#define CSR_PSKEY_USB_VM_CONTROL 0x03c0 /* bool */
+#define CSR_PSKEY_MR_ANA_RX_FTRIM 0x03bf /* uint16 */
+#define CSR_PSKEY_I2C_CONFIG 0x03be /* uint16 */
+#define CSR_PSKEY_IQ_LVL_RX 0x03bd /* uint16 */
+#define CSR_PSKEY_MR_TX_FILTER_CONFIG 0x03bb /* uint32 */
+#define CSR_PSKEY_MR_TX_CONFIG2 0x03ba /* uint16 */
+#define CSR_PSKEY_USB_DONT_RESET_BOOTMODE_ON_HOST_RESET 0x03b9 /* bool */
+#define CSR_PSKEY_LC_USE_THROTTLING 0x03b8 /* bool */
+#define CSR_PSKEY_CHARGER_TRIM 0x03b7 /* uint16 */
+#define CSR_PSKEY_CLOCK_REQUEST_FEATURES 0x03b6 /* uint16 */
+#define CSR_PSKEY_TRANSMIT_OFFSET_CLASS1 0x03b4 /* int16 */
+#define CSR_PSKEY_TX_AVOID_PA_CLASS1_PIO 0x03b3 /* uint16 */
+#define CSR_PSKEY_MR_PIO_CONFIG 0x03b2 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG2 0x03b1 /* uint8 */
+#define CSR_PSKEY_CLASS1_IQ_LVL 0x03b0 /* uint16 */
+#define CSR_PSKEY_CLASS1_TX_CONFIG2 0x03af /* uint16 */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1 0x03ae /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1 0x03ad /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR 0x03ac /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER 0x03ab /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD 0x03aa /* temperature_calibration[] */
+#define CSR_PSKEY_RX_MR_EQ_TAPS 0x03a9 /* uint16[] */
+#define CSR_PSKEY_TX_PRE_LVL_CLASS1 0x03a8 /* uint8 */
+#define CSR_PSKEY_ANALOGUE_ATTENUATOR 0x03a7 /* bool */
+#define CSR_PSKEY_MR_RX_FILTER_TRIM 0x03a6 /* uint16 */
+#define CSR_PSKEY_MR_RX_FILTER_RESPONSE 0x03a5 /* int16[] */
+#define CSR_PSKEY_PIO_WAKEUP_STATE 0x039f /* uint16 */
+#define CSR_PSKEY_MR_TX_IF_ATTEN_OFF_TEMP 0x0394 /* int16 */
+#define CSR_PSKEY_LO_DIV_LATCH_BYPASS 0x0393 /* bool */
+#define CSR_PSKEY_LO_VCO_STANDBY 0x0392 /* bool */
+#define CSR_PSKEY_SLOW_CLOCK_FILTER_SHIFT 0x0391 /* uint16 */
+#define CSR_PSKEY_SLOW_CLOCK_FILTER_DIVIDER 0x0390 /* uint16 */
+#define CSR_PSKEY_USB_ATTRIBUTES_POWER 0x03f2 /* bool */
+#define CSR_PSKEY_USB_ATTRIBUTES_WAKEUP 0x03f3 /* bool */
+#define CSR_PSKEY_DFU_ATTRIBUTES_MANIFESTATION_TOLERANT 0x03f4 /* bool */
+#define CSR_PSKEY_DFU_ATTRIBUTES_CAN_UPLOAD 0x03f5 /* bool */
+#define CSR_PSKEY_DFU_ATTRIBUTES_CAN_DOWNLOAD 0x03f6 /* bool */
+#define CSR_PSKEY_UART_CONFIG_STOP_BITS 0x03fc /* bool */
+#define CSR_PSKEY_UART_CONFIG_PARITY_BIT 0x03fd /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_FLOW_CTRL_EN 0x03fe /* bool */
+#define CSR_PSKEY_UART_CONFIG_RTS_AUTO_EN 0x03ff /* bool */
+#define CSR_PSKEY_UART_CONFIG_RTS 0x0400 /* bool */
+#define CSR_PSKEY_UART_CONFIG_TX_ZERO_EN 0x0401 /* bool */
+#define CSR_PSKEY_UART_CONFIG_NON_BCSP_EN 0x0402 /* bool */
+#define CSR_PSKEY_UART_CONFIG_RX_RATE_DELAY 0x0403 /* uint16 */
+#define CSR_PSKEY_UART_SEQ_TIMEOUT 0x0405 /* uint16 */
+#define CSR_PSKEY_UART_SEQ_RETRIES 0x0406 /* uint16 */
+#define CSR_PSKEY_UART_SEQ_WINSIZE 0x0407 /* uint16 */
+#define CSR_PSKEY_UART_USE_CRC_ON_TX 0x0408 /* bool */
+#define CSR_PSKEY_UART_HOST_INITIAL_STATE 0x0409 /* hwakeup_state */
+#define CSR_PSKEY_UART_HOST_ATTENTION_SPAN 0x040a /* uint16 */
+#define CSR_PSKEY_UART_HOST_WAKEUP_TIME 0x040b /* uint16 */
+#define CSR_PSKEY_UART_HOST_WAKEUP_WAIT 0x040c /* uint16 */
+#define CSR_PSKEY_BCSP_LM_MODE 0x0410 /* uint16 */
+#define CSR_PSKEY_BCSP_LM_SYNC_RETRIES 0x0411 /* uint16 */
+#define CSR_PSKEY_BCSP_LM_TSHY 0x0412 /* uint16 */
+#define CSR_PSKEY_UART_DFU_CONFIG_STOP_BITS 0x0417 /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_PARITY_BIT 0x0418 /* uint16 */
+#define CSR_PSKEY_UART_DFU_CONFIG_FLOW_CTRL_EN 0x0419 /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_RTS_AUTO_EN 0x041a /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_RTS 0x041b /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_TX_ZERO_EN 0x041c /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_NON_BCSP_EN 0x041d /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_RX_RATE_DELAY 0x041e /* uint16 */
+#define CSR_PSKEY_AMUX_AIO0 0x041f /* ana_amux_sel */
+#define CSR_PSKEY_AMUX_AIO1 0x0420 /* ana_amux_sel */
+#define CSR_PSKEY_AMUX_AIO2 0x0421 /* ana_amux_sel */
+#define CSR_PSKEY_AMUX_AIO3 0x0422 /* ana_amux_sel */
+#define CSR_PSKEY_LOCAL_NAME_SIMPLIFIED 0x0423 /* local_name_complete */
+#define CSR_PSKEY_EXTENDED_STUB 0x2001 /* uint16 */
+
+char *csr_builddeftostr(uint16_t def);
+char *csr_buildidtostr(uint16_t id);
+char *csr_chipvertostr(uint16_t ver, uint16_t rev);
+char *csr_pskeytostr(uint16_t pskey);
+char *csr_pskeytoval(uint16_t pskey);
+
+int csr_open_hci(char *device);
+int csr_read_hci(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_hci(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_hci(void);
+
+int csr_open_usb(char *device);
+int csr_read_usb(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_usb(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_usb(void);
+
+int csr_open_bcsp(char *device, speed_t bcsp_rate);
+int csr_read_bcsp(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_bcsp(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_bcsp(void);
+
+int csr_open_h4(char *device);
+int csr_read_h4(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_h4(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_h4(void);
+
+int csr_open_3wire(char *device);
+int csr_read_3wire(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_3wire(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_3wire(void);
+
+int csr_write_varid_valueless(int dd, uint16_t seqnum, uint16_t varid);
+int csr_write_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length);
+int csr_read_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length);
+int csr_read_varid_uint16(int dd, uint16_t seqnum, uint16_t varid, uint16_t *value);
+int csr_read_varid_uint32(int dd, uint16_t seqnum, uint16_t varid, uint32_t *value);
+int csr_read_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length);
+int csr_write_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length);
+int csr_read_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t *value);
+int csr_write_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t value);
+int csr_read_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t *value);
+int csr_write_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t value);
+
+int psr_put(uint16_t pskey, uint8_t *value, uint16_t size);
+int psr_get(uint16_t *pskey, uint8_t *value, uint16_t *size);
+int psr_read(const char *filename);
+int psr_print(void);
diff --git a/external/cache/sources/hcitools/hciattach.c b/external/cache/sources/hcitools/hciattach.c
new file mode 100644
index 0000000..9e994f9
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach.c
@@ -0,0 +1,1513 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky
+ * Copyright (C) 2002-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+static volatile sig_atomic_t __io_canceled = 0;
+
+static void sig_hup(int sig)
+{
+}
+
+static void sig_term(int sig)
+{
+ __io_canceled = 1;
+}
+
+static void sig_alarm(int sig)
+{
+ fprintf(stderr, "Initialization timed out.\n");
+ exit(1);
+}
+
+int uart_speed(int s)
+{
+ switch (s) {
+ case 9600:
+ return B9600;
+ case 19200:
+ return B19200;
+ case 38400:
+ return B38400;
+ case 57600:
+ return B57600;
+ case 115200:
+ return B115200;
+ case 230400:
+ return B230400;
+ case 460800:
+ return B460800;
+ case 500000:
+ return B500000;
+ case 576000:
+ return B576000;
+ case 921600:
+ return B921600;
+ case 1000000:
+ return B1000000;
+ case 1152000:
+ return B1152000;
+ case 1500000:
+ return B1500000;
+ case 2000000:
+ return B2000000;
+#ifdef B2500000
+ case 2500000:
+ return B2500000;
+#endif
+#ifdef B3000000
+ case 3000000:
+ return B3000000;
+#endif
+#ifdef B3500000
+ case 3500000:
+ return B3500000;
+#endif
+#ifdef B3710000
+ case 3710000
+ return B3710000;
+#endif
+#ifdef B4000000
+ case 4000000:
+ return B4000000;
+#endif
+ default:
+ return B57600;
+ }
+}
+
+int set_speed(int fd, struct termios *ti, int speed)
+{
+ if (cfsetospeed(ti, uart_speed(speed)) < 0)
+ return -errno;
+
+ if (cfsetispeed(ti, uart_speed(speed)) < 0)
+ return -errno;
+
+ if (tcsetattr(fd, TCSANOW, ti) < 0)
+ return -errno;
+
+ return 0;
+}
+
+/*
+ * Read an HCI event from the given file descriptor.
+ */
+int read_hci_event(int fd, unsigned char* buf, int size)
+{
+ int remain, r;
+ int count = 0;
+
+ if (size <= 0)
+ return -1;
+
+ /* The first byte identifies the packet type. For HCI event packets, it
+ * should be 0x04, so we read until we get to the 0x04. */
+ while (1) {
+ r = read(fd, buf, 1);
+ if (r <= 0)
+ return -1;
+ if (buf[0] == 0x04)
+ break;
+ }
+ count++;
+
+ /* The next two bytes are the event code and parameter total length. */
+ while (count < 3) {
+ r = read(fd, buf + count, 3 - count);
+ if (r <= 0)
+ return -1;
+ count += r;
+ }
+
+ /* Now we read the parameters. */
+ if (buf[2] < (size - 3))
+ remain = buf[2];
+ else
+ remain = size - 3;
+
+ while ((count - 3) < remain) {
+ r = read(fd, buf + count, remain - (count - 3));
+ if (r <= 0)
+ return -1;
+ count += r;
+ }
+
+ return count;
+}
+
+/*
+ * Ericsson specific initialization
+ */
+static int ericsson(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x09;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x01;
+
+ switch (u->speed) {
+ case 57600:
+ cmd[4] = 0x03;
+ break;
+ case 115200:
+ cmd[4] = 0x02;
+ break;
+ case 230400:
+ cmd[4] = 0x01;
+ break;
+ case 460800:
+ cmd[4] = 0x00;
+ break;
+ case 921600:
+ cmd[4] = 0x20;
+ break;
+ case 2000000:
+ cmd[4] = 0x25;
+ break;
+ case 3000000:
+ cmd[4] = 0x27;
+ break;
+ case 4000000:
+ cmd[4] = 0x2B;
+ break;
+ default:
+ cmd[4] = 0x03;
+ u->speed = 57600;
+ fprintf(stderr, "Invalid speed requested, using %d bps instead\n", u->speed);
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 5) != 5) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+/*
+ * Digianswer specific initialization
+ */
+static int digi(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+
+ /* DigiAnswer set baud rate command */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x07;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x01;
+
+ switch (u->speed) {
+ case 57600:
+ cmd[4] = 0x08;
+ break;
+ case 115200:
+ cmd[4] = 0x09;
+ break;
+ default:
+ cmd[4] = 0x09;
+ u->speed = 115200;
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 5) != 5) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+static int texas(int fd, struct uart_t *u, struct termios *ti)
+{
+ return texas_init(fd, &u->speed, ti);
+}
+
+static int texas2(int fd, struct uart_t *u, struct termios *ti)
+{
+ return texas_post(fd, ti);
+}
+
+static int texasalt(int fd, struct uart_t *u, struct termios *ti)
+{
+ return texasalt_init(fd, u->speed, ti);
+}
+
+static int ath3k_ps(int fd, struct uart_t *u, struct termios *ti)
+{
+ return ath3k_init(fd, u->speed, u->init_speed, u->bdaddr, ti);
+}
+
+static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti)
+{
+ return ath3k_post(fd, u->pm);
+}
+
+static int qualcomm(int fd, struct uart_t *u, struct termios *ti)
+{
+ return qualcomm_init(fd, u->speed, ti, u->bdaddr);
+}
+
+static int intel(int fd, struct uart_t *u, struct termios *ti)
+{
+ return intel_init(fd, u->init_speed, &u->speed, ti);
+}
+
+static int bcm43xx(int fd, struct uart_t *u, struct termios *ti)
+{
+ return bcm43xx_init(fd, u->speed, ti, u->bdaddr);
+}
+
+//Realtek_add_start
+//add realtek Bluetooth init and post function.
+static int realtek_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "Realtek Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );
+ return rtk_init(fd, u->proto, u->speed, ti);
+}
+
+static int realtek_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "Realtek Bluetooth post process\n");
+ return rtk_post(fd, u->proto, ti);
+}
+
+// add xradio Bluetooth init and post function.
+static int xradio_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "XRADIO Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );
+ return xr_init(fd, u, ti);
+}
+
+static int xradio_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "XRADIO Bluetooth post process\n");
+ return xr_post(fd, u, ti);
+}
+
+// add sprd Bluetooth init and post function.
+static int sprd_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "SPRD Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );
+ return sprd_config_init(fd, u, ti);
+}
+
+static int sprd_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "SPRD Bluetooth post process\n");
+ return sprd_config_post(fd, u, ti);
+}
+
+static int read_check(int fd, void *buf, int count)
+{
+ int res;
+
+ do {
+ res = read(fd, buf, count);
+ if (res != -1) {
+ buf += res;
+ count -= res;
+ }
+ } while (count && (errno == 0 || errno == EINTR));
+
+ if (count)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * BCSP specific initialization
+ */
+static int serial_fd;
+static int bcsp_max_retries = 10;
+
+static void bcsp_tshy_sig_alarm(int sig)
+{
+ unsigned char bcsp_sync_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xda,0xdc,0xed,0xed,0xc0};
+ static int retries = 0;
+
+ if (retries < bcsp_max_retries) {
+ retries++;
+ if (write(serial_fd, &bcsp_sync_pkt, 10) < 0)
+ return;
+ alarm(1);
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ fprintf(stderr, "BCSP initialization timed out\n");
+ exit(1);
+}
+
+static void bcsp_tconf_sig_alarm(int sig)
+{
+ unsigned char bcsp_conf_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xad,0xef,0xac,0xed,0xc0};
+ static int retries = 0;
+
+ if (retries < bcsp_max_retries){
+ retries++;
+ if (write(serial_fd, &bcsp_conf_pkt, 10) < 0)
+ return;
+ alarm(1);
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ fprintf(stderr, "BCSP initialization timed out\n");
+ exit(1);
+}
+
+static int bcsp(int fd, struct uart_t *u, struct termios *ti)
+{
+ unsigned char byte, bcsph[4], bcspp[4],
+ bcsp_sync_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xac,0xaf,0xef,0xee,0xc0},
+ bcsp_conf_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xde,0xad,0xd0,0xd0,0xc0},
+ bcspsync[4] = {0xda, 0xdc, 0xed, 0xed},
+ bcspsyncresp[4] = {0xac,0xaf,0xef,0xee},
+ bcspconf[4] = {0xad,0xef,0xac,0xed},
+ bcspconfresp[4] = {0xde,0xad,0xd0,0xd0};
+ struct sigaction sa;
+ int len;
+
+ if (set_speed(fd, ti, u->speed) < 0) {
+ perror("Can't set default baud rate");
+ return -1;
+ }
+
+ ti->c_cflag |= PARENB;
+ ti->c_cflag &= ~(PARODD);
+
+ if (tcsetattr(fd, TCSANOW, ti) < 0) {
+ perror("Can't set port settings");
+ return -1;
+ }
+
+ alarm(0);
+
+ serial_fd = fd;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = bcsp_tshy_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ /* State = shy */
+
+ bcsp_tshy_sig_alarm(0);
+ while (1) {
+ do {
+ if (read_check(fd, &byte, 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (byte != 0xC0);
+
+ do {
+ if ( read_check(fd, &bcsph[0], 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (bcsph[0] == 0xC0);
+
+ if ( read_check(fd, &bcsph[1], 3) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3])
+ continue;
+ if (bcsph[1] != 0x41 || bcsph[2] != 0x00)
+ continue;
+
+ if (read_check(fd, &bcspp, 4) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (!memcmp(bcspp, bcspsync, 4)) {
+ if (write(fd, &bcsp_sync_resp_pkt,10) < 0)
+ return -1;
+ } else if (!memcmp(bcspp, bcspsyncresp, 4))
+ break;
+ }
+
+ /* State = curious */
+
+ alarm(0);
+ sa.sa_handler = bcsp_tconf_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+ alarm(1);
+
+ while (1) {
+ do {
+ if (read_check(fd, &byte, 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (byte != 0xC0);
+
+ do {
+ if (read_check(fd, &bcsph[0], 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (bcsph[0] == 0xC0);
+
+ if (read_check(fd, &bcsph[1], 3) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3])
+ continue;
+
+ if (bcsph[1] != 0x41 || bcsph[2] != 0x00)
+ continue;
+
+ if (read_check(fd, &bcspp, 4) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (!memcmp(bcspp, bcspsync, 4))
+ len = write(fd, &bcsp_sync_resp_pkt, 10);
+ else if (!memcmp(bcspp, bcspconf, 4))
+ len = write(fd, &bcsp_conf_resp_pkt, 10);
+ else if (!memcmp(bcspp, bcspconfresp, 4))
+ break;
+ else
+ continue;
+
+ if (len < 0)
+ return -errno;
+ }
+
+ /* State = garrulous */
+
+ return 0;
+}
+
+/*
+ * CSR specific initialization
+ * Inspired strongly by code in OpenBT and experimentations with Brainboxes
+ * Pcmcia card.
+ * Jean Tourrilhes - 14.11.01
+ */
+static int csr(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 10000000}; /* 10ms - be generous */
+ unsigned char cmd[30]; /* Command */
+ unsigned char resp[30]; /* Response */
+ int clen = 0; /* Command len */
+ static int csr_seq = 0; /* Sequence number of command */
+ int divisor;
+
+ /* It seems that if we set the CSR UART speed straight away, it
+ * won't work, the CSR UART gets into a state where we can't talk
+ * to it anymore.
+ * On the other hand, doing a read before setting the CSR speed
+ * seems to be ok.
+ * Therefore, the strategy is to read the build ID (useful for
+ * debugging) and only then set the CSR UART speed. Doing like
+ * this is more complex but at least it works ;-)
+ * The CSR UART control may be slow to wake up or something because
+ * every time I read its speed, its bogus...
+ * Jean II */
+
+ /* Try to read the build ID of the CSR chip */
+ clen = 5 + (5 + 6) * 2;
+ /* HCI header */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x00; /* CSR command */
+ cmd[2] = 0xfc; /* MANUFACTURER_SPEC */
+ cmd[3] = 1 + (5 + 6) * 2; /* len */
+ /* CSR MSG header */
+ cmd[4] = 0xC2; /* first+last+channel=BCC */
+ /* CSR BCC header */
+ cmd[5] = 0x00; /* type = GET-REQ */
+ cmd[6] = 0x00; /* - msB */
+ cmd[7] = 5 + 4; /* len */
+ cmd[8] = 0x00; /* - msB */
+ cmd[9] = csr_seq & 0xFF;/* seq num */
+ cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */
+ csr_seq++;
+ cmd[11] = 0x19; /* var_id = CSR_CMD_BUILD_ID */
+ cmd[12] = 0x28; /* - msB */
+ cmd[13] = 0x00; /* status = STATUS_OK */
+ cmd[14] = 0x00; /* - msB */
+ /* CSR BCC payload */
+ memset(cmd + 15, 0, 6 * 2);
+
+ /* Send command */
+ do {
+ if (write(fd, cmd, clen) != clen) {
+ perror("Failed to write init command (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Event code 0xFF is for vendor-specific events, which is
+ * what we're looking for. */
+ } while (resp[1] != 0xFF);
+
+#ifdef CSR_DEBUG
+ {
+ char temp[512];
+ int i;
+ for (i=0; i < rlen; i++)
+ sprintf(temp + (i*3), "-%02X", resp[i]);
+ fprintf(stderr, "Reading CSR build ID %d [%s]\n", rlen, temp + 1);
+ // In theory, it should look like :
+ // 04-FF-13-FF-01-00-09-00-00-00-19-28-00-00-73-00-00-00-00-00-00-00
+ }
+#endif
+ /* Display that to user */
+ fprintf(stderr, "CSR build ID 0x%02X-0x%02X\n",
+ resp[15] & 0xFF, resp[14] & 0xFF);
+
+ /* Try to read the current speed of the CSR chip */
+ clen = 5 + (5 + 4)*2;
+ /* -- HCI header */
+ cmd[3] = 1 + (5 + 4)*2; /* len */
+ /* -- CSR BCC header -- */
+ cmd[9] = csr_seq & 0xFF; /* seq num */
+ cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */
+ csr_seq++;
+ cmd[11] = 0x02; /* var_id = CONFIG_UART */
+ cmd[12] = 0x68; /* - msB */
+
+#ifdef CSR_DEBUG
+ /* Send command */
+ do {
+ if (write(fd, cmd, clen) != clen) {
+ perror("Failed to write init command (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Event code 0xFF is for vendor-specific events, which is
+ * what we're looking for. */
+ } while (resp[1] != 0xFF);
+
+ {
+ char temp[512];
+ int i;
+ for (i=0; i < rlen; i++)
+ sprintf(temp + (i*3), "-%02X", resp[i]);
+ fprintf(stderr, "Reading CSR UART speed %d [%s]\n", rlen, temp+1);
+ }
+#endif
+
+ if (u->speed > 1500000) {
+ fprintf(stderr, "Speed %d too high. Remaining at %d baud\n",
+ u->speed, u->init_speed);
+ u->speed = u->init_speed;
+ } else if (u->speed != 57600 && uart_speed(u->speed) == B57600) {
+ /* Unknown speed. Why oh why can't we just pass an int to the kernel? */
+ fprintf(stderr, "Speed %d unrecognised. Remaining at %d baud\n",
+ u->speed, u->init_speed);
+ u->speed = u->init_speed;
+ }
+ if (u->speed == u->init_speed)
+ return 0;
+
+ /* Now, create the command that will set the UART speed */
+ /* CSR BCC header */
+ cmd[5] = 0x02; /* type = SET-REQ */
+ cmd[6] = 0x00; /* - msB */
+ cmd[9] = csr_seq & 0xFF; /* seq num */
+ cmd[10] = (csr_seq >> 8) & 0xFF;/* - msB */
+ csr_seq++;
+
+ divisor = (u->speed*64+7812)/15625;
+
+ /* No parity, one stop bit -> divisor |= 0x0000; */
+ cmd[15] = (divisor) & 0xFF; /* divider */
+ cmd[16] = (divisor >> 8) & 0xFF; /* - msB */
+ /* The rest of the payload will be 0x00 */
+
+#ifdef CSR_DEBUG
+ {
+ char temp[512];
+ int i;
+ for(i = 0; i < clen; i++)
+ sprintf(temp + (i*3), "-%02X", cmd[i]);
+ fprintf(stderr, "Writing CSR UART speed %d [%s]\n", clen, temp + 1);
+ // In theory, it should look like :
+ // 01-00-FC-13-C2-02-00-09-00-03-00-02-68-00-00-BF-0E-00-00-00-00-00-00
+ // 01-00-FC-13-C2-02-00-09-00-01-00-02-68-00-00-D8-01-00-00-00-00-00-00
+ }
+#endif
+
+ /* Send the command to set the CSR UART speed */
+ if (write(fd, cmd, clen) != clen) {
+ perror("Failed to write init command (SET_UART_SPEED)");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+/*
+ * Silicon Wave specific initialization
+ * Thomas Moser
+ */
+static int swave(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = { 0, 500000 };
+ char cmd[10], rsp[100];
+ int r;
+
+ // Silicon Wave set baud rate command
+ // see HCI Vendor Specific Interface from Silicon Wave
+ // first send a "param access set" command to set the
+ // appropriate data fields in RAM. Then send a "HCI Reset
+ // Subcommand", e.g. "soft reset" to make the changes effective.
+
+ cmd[0] = HCI_COMMAND_PKT; // it's a command packet
+ cmd[1] = 0x0B; // OCF 0x0B = param access set
+ cmd[2] = 0xfc; // OGF bx111111 = vendor specific
+ cmd[3] = 0x06; // 6 bytes of data following
+ cmd[4] = 0x01; // param sub command
+ cmd[5] = 0x11; // tag 17 = 0x11 = HCI Transport Params
+ cmd[6] = 0x03; // length of the parameter following
+ cmd[7] = 0x01; // HCI Transport flow control enable
+ cmd[8] = 0x01; // HCI Transport Type = UART
+
+ switch (u->speed) {
+ case 19200:
+ cmd[9] = 0x03;
+ break;
+ case 38400:
+ cmd[9] = 0x02;
+ break;
+ case 57600:
+ cmd[9] = 0x01;
+ break;
+ case 115200:
+ cmd[9] = 0x00;
+ break;
+ default:
+ u->speed = 115200;
+ cmd[9] = 0x00;
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 10) != 10) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ // We should wait for a "GET Event" to confirm the success of
+ // the baud rate setting. Wait some time before reading. Better:
+ // read with timeout, parse data
+ // until correct answer, else error handling ... todo ...
+
+ nanosleep(&tm, NULL);
+
+ r = read(fd, rsp, sizeof(rsp));
+ if (r > 0) {
+ // guess it's okay, but we should parse the reply. But since
+ // I don't react on an error anyway ... todo
+ // Response packet format:
+ // 04 Event
+ // FF Vendor specific
+ // 07 Parameter length
+ // 0B Subcommand
+ // 01 Setevent
+ // 11 Tag specifying HCI Transport Layer Parameter
+ // 03 length
+ // 01 flow on
+ // 01 Hci Transport type = Uart
+ // xx Baud rate set (see above)
+ } else {
+ // ups, got error.
+ return -1;
+ }
+
+ // we probably got the reply. Now we must send the "soft reset"
+ // which is standard HCI RESET.
+
+ cmd[0] = HCI_COMMAND_PKT; // it's a command packet
+ cmd[1] = 0x03;
+ cmd[2] = 0x0c;
+ cmd[3] = 0x00;
+
+ /* Send reset command */
+ if (write(fd, cmd, 4) != 4) {
+ perror("Can't write Silicon Wave reset cmd.");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+
+ // now the uart baud rate on the silicon wave module is set and effective.
+ // change our own baud rate as well. Then there is a reset event coming in
+ // on the *new* baud rate. This is *undocumented*! The packet looks like this:
+ // 04 FF 01 0B (which would make that a confirmation of 0x0B = "Param
+ // subcommand class". So: change to new baud rate, read with timeout, parse
+ // data, error handling. BTW: all param access in Silicon Wave is done this way.
+ // Maybe this code would belong in a separate file, or at least code reuse...
+
+ return 0;
+}
+
+/*
+ * ST Microelectronics specific initialization
+ * Marcel Holtmann
+ */
+static int st(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+
+ /* ST Microelectronics set baud rate command */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x46; // OCF = Hci_Cmd_ST_Set_Uart_Baud_Rate
+ cmd[2] = 0xfc; // OGF = Vendor specific
+ cmd[3] = 0x01;
+
+ switch (u->speed) {
+ case 9600:
+ cmd[4] = 0x09;
+ break;
+ case 19200:
+ cmd[4] = 0x0b;
+ break;
+ case 38400:
+ cmd[4] = 0x0d;
+ break;
+ case 57600:
+ cmd[4] = 0x0e;
+ break;
+ case 115200:
+ cmd[4] = 0x10;
+ break;
+ case 230400:
+ cmd[4] = 0x12;
+ break;
+ case 460800:
+ cmd[4] = 0x13;
+ break;
+ case 921600:
+ cmd[4] = 0x14;
+ break;
+ default:
+ cmd[4] = 0x10;
+ u->speed = 115200;
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 5) != 5) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+static int stlc2500(int fd, struct uart_t *u, struct termios *ti)
+{
+ bdaddr_t bdaddr;
+ unsigned char resp[10];
+ int n;
+ int rvalue;
+
+ /* STLC2500 has an ericsson core */
+ rvalue = ericsson(fd, u, ti);
+ if (rvalue != 0)
+ return rvalue;
+
+#ifdef STLC2500_DEBUG
+ fprintf(stderr, "Setting speed\n");
+#endif
+ if (set_speed(fd, ti, u->speed) < 0) {
+ perror("Can't set baud rate");
+ return -1;
+ }
+
+#ifdef STLC2500_DEBUG
+ fprintf(stderr, "Speed set...\n");
+#endif
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 10)) < 0) {
+ fprintf(stderr, "Failed to set baud rate on chip\n");
+ return -1;
+ }
+
+#ifdef STLC2500_DEBUG
+ for (i = 0; i < n; i++) {
+ fprintf(stderr, "resp[%d] = %02x\n", i, resp[i]);
+ }
+#endif
+
+ str2ba(u->bdaddr, &bdaddr);
+ return stlc2500_init(fd, &bdaddr);
+}
+
+static int bgb2xx(int fd, struct uart_t *u, struct termios *ti)
+{
+ bdaddr_t bdaddr;
+
+ str2ba(u->bdaddr, &bdaddr);
+
+ return bgb2xx_init(fd, &bdaddr);
+}
+
+/*
+ * Broadcom specific initialization
+ * Extracted from Jungo openrg
+ */
+static int bcm2035(int fd, struct uart_t *u, struct termios *ti)
+{
+ int n;
+ unsigned char cmd[30], resp[30];
+
+ /* Reset the BT Chip */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x03;
+ cmd[2] = 0x0c;
+ cmd[3] = 0x00;
+
+ /* Send command */
+ if (write(fd, cmd, 4) != 4) {
+ fprintf(stderr, "Failed to write reset command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 4)) < 0) {
+ fprintf(stderr, "Failed to reset chip\n");
+ return -1;
+ }
+
+ if (u->bdaddr != NULL) {
+ /* Set BD_ADDR */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x06;
+ str2ba(u->bdaddr, (bdaddr_t *) (cmd + 4));
+
+ /* Send command */
+ if (write(fd, cmd, 10) != 10) {
+ fprintf(stderr, "Failed to write BD_ADDR command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 10)) < 0) {
+ fprintf(stderr, "Failed to set BD_ADDR\n");
+ return -1;
+ }
+ }
+
+ /* Read the local version info */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ /* Send command */
+ if (write(fd, cmd, 4) != 4) {
+ fprintf(stderr, "Failed to write \"read local version\" "
+ "command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 4)) < 0) {
+ fprintf(stderr, "Failed to read local version\n");
+ return -1;
+ }
+
+ /* Read the local supported commands info */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x02;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ /* Send command */
+ if (write(fd, cmd, 4) != 4) {
+ fprintf(stderr, "Failed to write \"read local supported "
+ "commands\" command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 4)) < 0) {
+ fprintf(stderr, "Failed to read local supported commands\n");
+ return -1;
+ }
+
+ /* Set the baud rate */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x18;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x02;
+ switch (u->speed) {
+ case 57600:
+ cmd[4] = 0x00;
+ cmd[5] = 0xe6;
+ break;
+ case 230400:
+ cmd[4] = 0x22;
+ cmd[5] = 0xfa;
+ break;
+ case 460800:
+ cmd[4] = 0x22;
+ cmd[5] = 0xfd;
+ break;
+ case 921600:
+ cmd[4] = 0x55;
+ cmd[5] = 0xff;
+ break;
+ default:
+ /* Default is 115200 */
+ cmd[4] = 0x00;
+ cmd[5] = 0xf3;
+ break;
+ }
+ fprintf(stderr, "Baud rate parameters: DHBR=0x%2x,DLBR=0x%2x\n",
+ cmd[4], cmd[5]);
+
+ /* Send command */
+ if (write(fd, cmd, 6) != 6) {
+ fprintf(stderr, "Failed to write \"set baud rate\" command\n");
+ return -1;
+ }
+
+ if ((n = read_hci_event(fd, resp, 6)) < 0) {
+ fprintf(stderr, "Failed to set baud rate\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+struct uart_t uart[] = {
+ { "any", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ { "ericsson", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, ericsson, NULL },
+
+ { "digi", 0x0000, 0x0000, HCI_UART_H4, 9600, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, digi, NULL },
+
+ { "bcsp", 0x0000, 0x0000, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter */
+ { "xircom", 0x0105, 0x080a, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* CSR Casira serial adapter or BrainBoxes serial dongle (BL642) */
+ { "csr", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* BrainBoxes PCMCIA card (BL620) */
+ { "bboxes", 0x0160, 0x0002, HCI_UART_H4, 115200, 460800,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* Silicon Wave kits */
+ { "swave", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, swave, NULL },
+
+ /* Texas Instruments Bluelink (BRF) modules */
+ { "texas", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, texas, texas2 },
+
+ { "texasalt", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, texasalt, NULL },
+
+ /* ST Microelectronics minikits based on STLC2410/STLC2415 */
+ { "st", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, st, NULL },
+
+ /* ST Microelectronics minikits based on STLC2500 */
+ { "stlc2500", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, "00:80:E1:00:AB:BA", stlc2500, NULL },
+
+ /* Philips generic Ericsson IP core based */
+ { "philips", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* Philips BGB2xx Module */
+ { "bgb2xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, "BD:B2:10:00:AB:BA", bgb2xx, NULL },
+
+ /* Sphinx Electronics PICO Card */
+ { "picocard", 0x025e, 0x1000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* Inventel BlueBird Module */
+ { "inventel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* COM One Platinium Bluetooth PC Card */
+ { "comone", 0xffff, 0x0101, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* TDK Bluetooth PC Card and IBM Bluetooth PC Card II */
+ { "tdk", 0x0105, 0x4254, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Socket Bluetooth CF Card (Rev G) */
+ { "socket", 0x0104, 0x0096, HCI_UART_BCSP, 230400, 230400,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* 3Com Bluetooth Card (Version 3.0) */
+ { "3com", 0x0101, 0x0041, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* AmbiCom BT2000C Bluetooth PC/CF Card */
+ { "bt2000c", 0x022d, 0x2000, HCI_UART_H4, 57600, 460800,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* Zoom Bluetooth PCMCIA Card */
+ { "zoom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Sitecom CN-504 PCMCIA Card */
+ { "sitecom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Billionton PCBTC1 PCMCIA Card */
+ { "billionton", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Broadcom BCM2035 */
+ { "bcm2035", 0x0A5C, 0x2035, HCI_UART_H4, 115200, 460800,
+ FLOW_CTL, DISABLE_PM, NULL, bcm2035, NULL },
+
+ /* Broadcom BCM43XX */
+ { "bcm43xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 3000000,
+ FLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL },
+
+ { "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm },
+
+ /* QUALCOMM BTS */
+ { "qualcomm", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, qualcomm, NULL },
+
+ /* Intel Bluetooth Module */
+ { "intel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, intel, NULL },
+
+ /* Three-wire UART */
+ { "3wire", 0x0000, 0x0000, HCI_UART_3WIRE, 115200, 115200,
+ 0, DISABLE_PM, NULL, NULL, NULL },
+
+ /* AMP controller UART */
+ { "amp", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ AMP_DEV, DISABLE_PM, NULL, NULL, NULL },
+
+//Realtek_add_start
+ /* Realtek Bluetooth H4*/
+ /* H4 will set 115200 baudrate and flow control enable by default*/
+ { "rtk_h4", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, DISABLE_PM, NULL, realtek_init, realtek_post},
+ /* Realtek Bluetooth H5*/
+ /* H5 will set 921600 baudrate and flow control disable by default */
+ /* H5 will be realtek's recommanded protocol */
+ { "rtk_h5", 0x0000, 0x0000, HCI_UART_3WIRE, 115200,115200, 0, DISABLE_PM, NULL, realtek_init, realtek_post},
+//Realtek_add_end
+
+ { "xradio", 0x0000, 0x0000, HCI_UART_H4, 115200, 1500000, 0, DISABLE_PM, NULL, xradio_init, xradio_post},
+ { "sprd", 0x0000, 0x0000, NULL, 115200, 1500000, FLOW_CTL, DISABLE_PM, NULL, sprd_init, sprd_post},
+
+ { NULL, 0 }
+};
+
+static struct uart_t * get_by_id(int m_id, int p_id)
+{
+ int i;
+ for (i = 0; uart[i].type; i++) {
+ if (uart[i].m_id == m_id && uart[i].p_id == p_id)
+ return &uart[i];
+ }
+ return NULL;
+}
+
+static struct uart_t * get_by_type(char *type)
+{
+ int i;
+ for (i = 0; uart[i].type; i++) {
+ if (!strcmp(uart[i].type, type))
+ return &uart[i];
+ }
+ return NULL;
+}
+
+/* Initialize UART driver */
+static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
+{
+ struct termios ti;
+ int fd, i;
+ unsigned long flags = 0;
+
+ if (raw)
+ flags |= 1 << HCI_UART_RAW_DEVICE;
+
+ if (u->flags & AMP_DEV)
+ flags |= 1 << HCI_UART_CREATE_AMP;
+
+ fd = open(dev, O_RDWR | O_NOCTTY);
+ if (fd < 0) {
+ perror("Can't open serial port");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (tcgetattr(fd, &ti) < 0) {
+ perror("Can't get port settings");
+ return -1;
+ }
+
+ cfmakeraw(&ti);
+
+ ti.c_cflag |= CLOCAL;
+ if (u->flags & FLOW_CTL)
+ ti.c_cflag |= CRTSCTS;
+ else
+ ti.c_cflag &= ~CRTSCTS;
+
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ perror("Can't set port settings");
+ return -1;
+ }
+
+ /* Set initial baudrate */
+ if (set_speed(fd, &ti, u->init_speed) < 0) {
+ perror("Can't set initial baud rate");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (send_break) {
+ tcsendbreak(fd, 0);
+ usleep(500000);
+ }
+
+ if (u->init && u->init(fd, u, &ti) < 0)
+ return -1;
+
+ tcflush(fd, TCIOFLUSH);
+
+ /* Set actual baudrate */
+ if (set_speed(fd, &ti, u->speed) < 0) {
+ perror("Can't set baud rate");
+ return -1;
+ }
+
+ /* Set TTY to N_HCI line discipline */
+ i = N_HCI;
+ if (ioctl(fd, TIOCSETD, &i) < 0) {
+ perror("Can't set line discipline");
+ return -1;
+ }
+
+ if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {
+ perror("Can't set UART flags");
+ return -1;
+ }
+
+ if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) {
+ perror("Can't set device");
+ return -1;
+ }
+
+ if (u->post && u->post(fd, u, &ti) < 0)
+ return -1;
+
+ return fd;
+}
+
+static void usage(void)
+{
+ printf("hciattach - HCI UART driver initialization utility\n");
+ printf("Usage:\n");
+ printf("\thciattach [-n] [-p] [-b] [-r] [-t timeout] [-s initial_speed] [speed] [flow|noflow] [bdaddr]\n");
+ printf("\thciattach -l\n");
+}
+
+int main(int argc, char *argv[])
+{
+ struct uart_t *u = NULL;
+ int detach, printpid, raw, opt, i, n, ld, err;
+ int to = 10;
+ int init_speed = 0;
+ int send_break = 0;
+ pid_t pid;
+ struct sigaction sa;
+ struct pollfd p;
+ sigset_t sigs;
+ char dev[PATH_MAX];
+
+ detach = 1;
+ printpid = 0;
+ raw = 0;
+
+ while ((opt=getopt(argc, argv, "bnpt:s:lr")) != EOF) {
+ switch(opt) {
+ case 'b':
+ send_break = 1;
+ break;
+
+ case 'n':
+ detach = 0;
+ break;
+
+ case 'p':
+ printpid = 1;
+ break;
+
+ case 't':
+ to = atoi(optarg);
+ break;
+
+ case 's':
+ init_speed = atoi(optarg);
+ break;
+
+ case 'l':
+ for (i = 0; uart[i].type; i++) {
+ printf("%-10s0x%04x,0x%04x\n", uart[i].type,
+ uart[i].m_id, uart[i].p_id);
+ }
+ exit(0);
+
+ case 'r':
+ raw = 1;
+ break;
+
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ n = argc - optind;
+ if (n < 2) {
+ usage();
+ exit(1);
+ }
+
+ for (n = 0; optind < argc; n++, optind++) {
+ char *opt;
+
+ opt = argv[optind];
+
+ switch(n) {
+ case 0:
+ dev[0] = 0;
+ if (!strchr(opt, '/'))
+ strcpy(dev, "/dev/");
+ strcat(dev, opt);
+ break;
+
+ case 1:
+ if (strchr(argv[optind], ',')) {
+ uint32_t m_id, p_id;
+ sscanf(argv[optind], "%x,%x", &m_id, &p_id);
+ u = get_by_id(m_id, p_id);
+ } else {
+ u = get_by_type(opt);
+ }
+
+ if (!u) {
+ fprintf(stderr, "Unknown device type or id\n");
+ exit(1);
+ }
+
+ break;
+
+ case 2:
+ u->speed = atoi(argv[optind]);
+ break;
+
+ case 3:
+ if (!strcmp("flow", argv[optind]))
+ u->flags |= FLOW_CTL;
+ else
+ u->flags &= ~FLOW_CTL;
+ break;
+
+ case 4:
+ if (!strcmp("sleep", argv[optind]))
+ u->pm = ENABLE_PM;
+ else
+ u->pm = DISABLE_PM;
+ break;
+
+ case 5:
+ u->bdaddr = argv[optind];
+ break;
+ }
+ }
+
+ if (!u) {
+ fprintf(stderr, "Unknown device type or id\n");
+ exit(1);
+ }
+
+ /* If user specified a initial speed, use that instead of
+ the hardware's default */
+ if (init_speed)
+ u->init_speed = init_speed;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ /* 10 seconds should be enough for initialization */
+ alarm(to);
+ bcsp_max_retries = to;
+
+ n = init_uart(dev, u, send_break, raw);
+ if (n < 0) {
+ perror("Can't initialize device");
+ exit(1);
+ }
+
+ printf("Device setup complete\n");
+
+ alarm(0);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = sig_term;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ sa.sa_handler = sig_hup;
+ sigaction(SIGHUP, &sa, NULL);
+
+ if (detach) {
+ if ((pid = fork())) {
+ if (printpid)
+ printf("%d\n", pid);
+ return 0;
+ }
+
+ for (i = 0; i < 20; i++)
+ if (i != n)
+ close(i);
+ }
+
+ p.fd = n;
+ p.events = POLLERR | POLLHUP;
+
+ sigfillset(&sigs);
+ sigdelset(&sigs, SIGCHLD);
+ sigdelset(&sigs, SIGPIPE);
+ sigdelset(&sigs, SIGTERM);
+ sigdelset(&sigs, SIGINT);
+ sigdelset(&sigs, SIGHUP);
+
+ while (!__io_canceled) {
+ p.revents = 0;
+ err = ppoll(&p, 1, NULL, &sigs);
+ if (err < 0 && errno == EINTR)
+ continue;
+ if (err)
+ break;
+ }
+
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(n, TIOCSETD, &ld) < 0) {
+ perror("Can't restore line discipline");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach.h b/external/cache/sources/hcitools/hciattach.h
new file mode 100644
index 0000000..f92af74
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include
+
+#include
+
+#ifndef N_HCI
+#define N_HCI 15
+#endif
+
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
+#define HCIUARTSETFLAGS _IOW('U', 203, int)
+#define HCIUARTGETFLAGS _IOR('U', 204, int)
+
+#define HCI_UART_H4 0
+#define HCI_UART_BCSP 1
+#define HCI_UART_3WIRE 2
+#define HCI_UART_H4DS 3
+#define HCI_UART_LL 4
+#define HCI_UART_ATH3K 5
+
+#define HCI_UART_RAW_DEVICE 0
+#define HCI_UART_RESET_ON_INIT 1
+#define HCI_UART_CREATE_AMP 2
+
+struct uart_t {
+ char *type;
+ int m_id;
+ int p_id;
+ int proto;
+ int init_speed;
+ int speed;
+ int flags;
+ int pm;
+ char *bdaddr;
+ int (*init) (int fd, struct uart_t *u, struct termios *ti);
+ int (*post) (int fd, struct uart_t *u, struct termios *ti);
+};
+
+#define FLOW_CTL 0x0001
+#define AMP_DEV 0x0002
+#define ENABLE_PM 1
+#define DISABLE_PM 0
+
+int read_hci_event(int fd, unsigned char *buf, int size);
+int set_speed(int fd, struct termios *ti, int speed);
+int uart_speed(int speed);
+
+int texas_init(int fd, int *speed, struct termios *ti);
+int texas_post(int fd, struct termios *ti);
+int texasalt_init(int fd, int speed, struct termios *ti);
+int stlc2500_init(int fd, bdaddr_t *bdaddr);
+int bgb2xx_init(int dd, bdaddr_t *bdaddr);
+int ath3k_init(int fd, int speed, int init_speed, char *bdaddr,
+ struct termios *ti);
+int ath3k_post(int fd, int pm);
+int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr);
+int intel_init(int fd, int init_speed, int *speed, struct termios *ti);
+int bcm43xx_init(int fd, int speed, struct termios *ti, const char *bdaddr);
+
+//Realtek_add_start
+//add realtek init and post process for realtek Bluetooth chip
+int rtk_init(int fd, int proto, int speed, struct termios *ti);
+int rtk_post(int fd, int proto, struct termios *ti);
+//Realtek_add_end
+
+// add xradio init and post process for xradio Bluetooth chip (xr829)
+int xr_init(int fd, struct uart_t *u, struct termios *ti);
+int xr_post(int fd, struct uart_t *u, struct termios *ti);
+
+// add sprd init and post process for sprd Bluetooth chip (UWE5622)
+int sprd_config_init(int fd, struct uart_t *u, struct termios *ti);
+int sprd_config_post(int fd, struct uart_t *u, struct termios *ti);
diff --git a/external/cache/sources/hcitools/hciattach_ath3k.c b/external/cache/sources/hcitools/hciattach_ath3k.c
new file mode 100644
index 0000000..23208c6
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_ath3k.c
@@ -0,0 +1,1044 @@
+/*
+ * Copyright (c) 2009-2010 Atheros Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define FW_PATH "/lib/firmware/ar3k/"
+
+struct ps_cfg_entry {
+ uint32_t id;
+ uint32_t len;
+ uint8_t *data;
+};
+
+struct ps_entry_type {
+ unsigned char type;
+ unsigned char array;
+};
+
+#define MAX_TAGS 50
+#define PS_HDR_LEN 4
+#define HCI_VENDOR_CMD_OGF 0x3F
+#define HCI_PS_CMD_OCF 0x0B
+
+struct ps_cfg_entry ps_list[MAX_TAGS];
+
+static void load_hci_ps_hdr(uint8_t *cmd, uint8_t ps_op, int len, int index)
+{
+ hci_command_hdr *ch = (void *)cmd;
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_PS_CMD_OCF));
+ ch->plen = len + PS_HDR_LEN;
+ cmd += HCI_COMMAND_HDR_SIZE;
+
+ cmd[0] = ps_op;
+ cmd[1] = index;
+ cmd[2] = index >> 8;
+ cmd[3] = len;
+}
+
+#define PS_EVENT_LEN 100
+
+/*
+ * Send HCI command and wait for command complete event.
+ * The event buffer has to be freed by the caller.
+ */
+static int send_hci_cmd_sync(int dev, uint8_t *cmd, int len, uint8_t **event)
+{
+ int err;
+ uint8_t *hci_event;
+ uint8_t pkt_type = HCI_COMMAND_PKT;
+
+ if (len == 0)
+ return len;
+
+ if (write(dev, &pkt_type, 1) != 1)
+ return -EILSEQ;
+ if (write(dev, (unsigned char *)cmd, len) != len)
+ return -EILSEQ;
+
+ hci_event = (uint8_t *)malloc(PS_EVENT_LEN);
+ if (!hci_event)
+ return -ENOMEM;
+
+ err = read_hci_event(dev, (unsigned char *)hci_event, PS_EVENT_LEN);
+ if (err > 0) {
+ *event = hci_event;
+ } else {
+ free(hci_event);
+ return -EILSEQ;
+ }
+
+ return len;
+}
+
+#define HCI_EV_SUCCESS 0x00
+
+static int read_ps_event(uint8_t *event, uint16_t ocf)
+{
+ hci_event_hdr *eh;
+ uint16_t opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, ocf));
+
+ event++;
+
+ eh = (void *)event;
+ event += HCI_EVENT_HDR_SIZE;
+
+ if (eh->evt == EVT_CMD_COMPLETE) {
+ evt_cmd_complete *cc = (void *)event;
+
+ event += EVT_CMD_COMPLETE_SIZE;
+
+ if (cc->opcode == opcode && event[0] == HCI_EV_SUCCESS)
+ return 0;
+ else
+ return -EILSEQ;
+ }
+
+ return -EILSEQ;
+}
+
+static int write_cmd(int fd, uint8_t *buffer, int len)
+{
+ uint8_t *event;
+ int err;
+
+ err = send_hci_cmd_sync(fd, buffer, len, &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+ free(event);
+
+ return err;
+}
+
+#define PS_WRITE 1
+#define PS_RESET 2
+#define WRITE_PATCH 8
+#define ENABLE_PATCH 11
+
+#define HCI_PS_CMD_HDR_LEN 7
+
+#define PS_RESET_PARAM_LEN 6
+#define HCI_MAX_CMD_SIZE 260
+#define PS_RESET_CMD_LEN (HCI_PS_CMD_HDR_LEN + PS_RESET_PARAM_LEN)
+
+#define PS_ID_MASK 0xFF
+
+/* Sends PS commands using vendor specficic HCI commands */
+static int write_ps_cmd(int fd, uint8_t opcode, uint32_t ps_param)
+{
+ uint8_t cmd[HCI_MAX_CMD_SIZE];
+ uint32_t i;
+
+ switch (opcode) {
+ case ENABLE_PATCH:
+ load_hci_ps_hdr(cmd, opcode, 0, 0x00);
+
+ if (write_cmd(fd, cmd, HCI_PS_CMD_HDR_LEN) < 0)
+ return -EILSEQ;
+ break;
+
+ case PS_RESET:
+ load_hci_ps_hdr(cmd, opcode, PS_RESET_PARAM_LEN, 0x00);
+
+ cmd[7] = 0x00;
+ cmd[PS_RESET_CMD_LEN - 2] = ps_param & PS_ID_MASK;
+ cmd[PS_RESET_CMD_LEN - 1] = (ps_param >> 8) & PS_ID_MASK;
+
+ if (write_cmd(fd, cmd, PS_RESET_CMD_LEN) < 0)
+ return -EILSEQ;
+ break;
+
+ case PS_WRITE:
+ for (i = 0; i < ps_param; i++) {
+ load_hci_ps_hdr(cmd, opcode, ps_list[i].len,
+ ps_list[i].id);
+
+ memcpy(&cmd[HCI_PS_CMD_HDR_LEN], ps_list[i].data,
+ ps_list[i].len);
+
+ if (write_cmd(fd, cmd, ps_list[i].len +
+ HCI_PS_CMD_HDR_LEN) < 0)
+ return -EILSEQ;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#define __is_delim(ch) ((ch) == ':')
+#define MAX_PREAMBLE_LEN 4
+
+/* Parse PS entry preamble of format [X:X] for main type and subtype */
+static int get_ps_type(char *ptr, int index, char *type, char *sub_type)
+{
+ int i;
+ int delim = FALSE;
+
+ if (index > MAX_PREAMBLE_LEN)
+ return -EILSEQ;
+
+ for (i = 1; i < index; i++) {
+ if (__is_delim(ptr[i])) {
+ delim = TRUE;
+ continue;
+ }
+
+ if (isalpha(ptr[i])) {
+ if (delim == FALSE)
+ (*type) = toupper(ptr[i]);
+ else
+ (*sub_type) = toupper(ptr[i]);
+ }
+ }
+
+ return 0;
+}
+
+#define ARRAY 'A'
+#define STRING 'S'
+#define DECIMAL 'D'
+#define BINARY 'B'
+
+#define PS_HEX 0
+#define PS_DEC 1
+
+static int get_input_format(char *buf, struct ps_entry_type *format)
+{
+ char *ptr = NULL;
+ char type = '\0';
+ char sub_type = '\0';
+
+ format->type = PS_HEX;
+ format->array = TRUE;
+
+ if (strstr(buf, "[") != buf)
+ return 0;
+
+ ptr = strstr(buf, "]");
+ if (!ptr)
+ return -EILSEQ;
+
+ if (get_ps_type(buf, ptr - buf, &type, &sub_type) < 0)
+ return -EILSEQ;
+
+ /* Check is data type is of array */
+ if (type == ARRAY || sub_type == ARRAY)
+ format->array = TRUE;
+
+ if (type == STRING || sub_type == STRING)
+ format->array = FALSE;
+
+ if (type == DECIMAL || type == BINARY)
+ format->type = PS_DEC;
+ else
+ format->type = PS_HEX;
+
+ return 0;
+}
+
+#define UNDEFINED 0xFFFF
+
+static unsigned int read_data_in_section(char *buf, struct ps_entry_type type)
+{
+ char *ptr = buf;
+
+ if (!buf)
+ return UNDEFINED;
+
+ if (buf == strstr(buf, "[")) {
+ ptr = strstr(buf, "]");
+ if (!ptr)
+ return UNDEFINED;
+
+ ptr++;
+ }
+
+ if (type.type == PS_HEX && type.array != TRUE)
+ return strtol(ptr, NULL, 16);
+
+ return UNDEFINED;
+}
+
+struct tag_info {
+ unsigned section;
+ unsigned line_count;
+ unsigned char_cnt;
+ unsigned byte_count;
+};
+
+static inline int update_char_count(const char *buf)
+{
+ char *end_ptr;
+
+ if (strstr(buf, "[") == buf) {
+ end_ptr = strstr(buf, "]");
+ if (!end_ptr)
+ return 0;
+ else
+ return (end_ptr - buf) + 1;
+ }
+
+ return 0;
+}
+
+/* Read PS entries as string, convert and add to Hex array */
+static void update_tag_data(struct ps_cfg_entry *tag,
+ struct tag_info *info, const char *ptr)
+{
+ char buf[3];
+
+ buf[2] = '\0';
+
+ strncpy(buf, &ptr[info->char_cnt], 2);
+ tag->data[info->byte_count] = strtol(buf, NULL, 16);
+ info->char_cnt += 3;
+ info->byte_count++;
+
+ strncpy(buf, &ptr[info->char_cnt], 2);
+ tag->data[info->byte_count] = strtol(buf, NULL, 16);
+ info->char_cnt += 3;
+ info->byte_count++;
+}
+
+#define PS_UNDEF 0
+#define PS_ID 1
+#define PS_LEN 2
+#define PS_DATA 3
+
+#define PS_MAX_LEN 500
+#define LINE_SIZE_MAX (PS_MAX_LEN * 2)
+#define ENTRY_PER_LINE 16
+
+#define __check_comment(buf) (((buf)[0] == '/') && ((buf)[1] == '/'))
+#define __skip_space(str) while (*(str) == ' ') ((str)++)
+
+static int ath_parse_ps(FILE *stream)
+{
+ char buf[LINE_SIZE_MAX + 1];
+ char *ptr;
+ uint8_t tag_cnt = 0;
+ int16_t byte_count = 0;
+ struct ps_entry_type format;
+ struct tag_info status = { 0, 0, 0, 0 };
+
+ do {
+ int read_count;
+ struct ps_cfg_entry *tag;
+
+ ptr = fgets(buf, LINE_SIZE_MAX, stream);
+ if (!ptr)
+ break;
+
+ __skip_space(ptr);
+ if (__check_comment(ptr))
+ continue;
+
+ /* Lines with a '#' will be followed by new PS entry */
+ if (ptr == strstr(ptr, "#")) {
+ if (status.section != PS_UNDEF) {
+ return -EILSEQ;
+ } else {
+ status.section = PS_ID;
+ continue;
+ }
+ }
+
+ tag = &ps_list[tag_cnt];
+
+ switch (status.section) {
+ case PS_ID:
+ if (get_input_format(ptr, &format) < 0)
+ return -EILSEQ;
+
+ tag->id = read_data_in_section(ptr, format);
+ status.section = PS_LEN;
+ break;
+
+ case PS_LEN:
+ if (get_input_format(ptr, &format) < 0)
+ return -EILSEQ;
+
+ byte_count = read_data_in_section(ptr, format);
+ if (byte_count > PS_MAX_LEN)
+ return -EILSEQ;
+
+ tag->len = byte_count;
+ tag->data = (uint8_t *)malloc(byte_count);
+
+ status.section = PS_DATA;
+ status.line_count = 0;
+ break;
+
+ case PS_DATA:
+ if (status.line_count == 0)
+ if (get_input_format(ptr, &format) < 0)
+ return -EILSEQ;
+
+ __skip_space(ptr);
+
+ status.char_cnt = update_char_count(ptr);
+
+ read_count = (byte_count > ENTRY_PER_LINE) ?
+ ENTRY_PER_LINE : byte_count;
+
+ if (format.type == PS_HEX && format.array == TRUE) {
+ while (read_count > 0) {
+ update_tag_data(tag, &status, ptr);
+ read_count -= 2;
+ }
+
+ if (byte_count > ENTRY_PER_LINE)
+ byte_count -= ENTRY_PER_LINE;
+ else
+ byte_count = 0;
+ }
+
+ status.line_count++;
+
+ if (byte_count == 0)
+ memset(&status, 0x00, sizeof(struct tag_info));
+
+ if (status.section == PS_UNDEF)
+ tag_cnt++;
+
+ if (tag_cnt == MAX_TAGS)
+ return -EILSEQ;
+ break;
+ }
+ } while (ptr);
+
+ return tag_cnt;
+}
+
+#define MAX_PATCH_CMD 244
+struct patch_entry {
+ int16_t len;
+ uint8_t data[MAX_PATCH_CMD];
+};
+
+#define SET_PATCH_RAM_ID 0x0D
+#define SET_PATCH_RAM_CMD_SIZE 11
+#define ADDRESS_LEN 4
+static int set_patch_ram(int dev, char *patch_loc, int len)
+{
+ int err;
+ uint8_t cmd[20];
+ int i, j;
+ char loc_byte[3];
+ uint8_t *event;
+ uint8_t *loc_ptr = &cmd[7];
+
+ if (!patch_loc)
+ return -1;
+
+ loc_byte[2] = '\0';
+
+ load_hci_ps_hdr(cmd, SET_PATCH_RAM_ID, ADDRESS_LEN, 0);
+
+ for (i = 0, j = 3; i < 4; i++, j--) {
+ loc_byte[0] = patch_loc[0];
+ loc_byte[1] = patch_loc[1];
+ loc_ptr[j] = strtol(loc_byte, NULL, 16);
+ patch_loc += 2;
+ }
+
+ err = send_hci_cmd_sync(dev, cmd, SET_PATCH_RAM_CMD_SIZE, &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+ free(event);
+
+ return err;
+}
+
+#define PATCH_LOC_KEY "DA:"
+#define PATCH_LOC_STRING_LEN 8
+static int ps_patch_download(int fd, FILE *stream)
+{
+ char byte[3];
+ char ptr[MAX_PATCH_CMD + 1];
+ int byte_cnt;
+ int patch_count = 0;
+ char patch_loc[PATCH_LOC_STRING_LEN + 1];
+
+ byte[2] = '\0';
+
+ while (fgets(ptr, MAX_PATCH_CMD, stream)) {
+ if (strlen(ptr) <= 1)
+ continue;
+ else if (strstr(ptr, PATCH_LOC_KEY) == ptr) {
+ strncpy(patch_loc, &ptr[sizeof(PATCH_LOC_KEY) - 1],
+ PATCH_LOC_STRING_LEN);
+ if (set_patch_ram(fd, patch_loc, sizeof(patch_loc)) < 0)
+ return -1;
+ } else if (isxdigit(ptr[0]))
+ break;
+ else
+ return -1;
+ }
+
+ byte_cnt = strtol(ptr, NULL, 16);
+
+ while (byte_cnt > 0) {
+ int i;
+ uint8_t cmd[HCI_MAX_CMD_SIZE];
+ struct patch_entry patch;
+
+ if (byte_cnt > MAX_PATCH_CMD)
+ patch.len = MAX_PATCH_CMD;
+ else
+ patch.len = byte_cnt;
+
+ for (i = 0; i < patch.len; i++) {
+ if (!fgets(byte, 3, stream))
+ return -1;
+
+ patch.data[i] = strtoul(byte, NULL, 16);
+ }
+
+ load_hci_ps_hdr(cmd, WRITE_PATCH, patch.len, patch_count);
+ memcpy(&cmd[HCI_PS_CMD_HDR_LEN], patch.data, patch.len);
+
+ if (write_cmd(fd, cmd, patch.len + HCI_PS_CMD_HDR_LEN) < 0)
+ return -1;
+
+ patch_count++;
+ byte_cnt = byte_cnt - MAX_PATCH_CMD;
+ }
+
+ if (write_ps_cmd(fd, ENABLE_PATCH, 0) < 0)
+ return -1;
+
+ return patch_count;
+}
+
+#define PS_RAM_SIZE 2048
+
+static int ps_config_download(int fd, int tag_count)
+{
+ if (write_ps_cmd(fd, PS_RESET, PS_RAM_SIZE) < 0)
+ return -1;
+
+ if (tag_count > 0)
+ if (write_ps_cmd(fd, PS_WRITE, tag_count) < 0)
+ return -1;
+ return 0;
+}
+
+#define PS_ASIC_FILE "PS_ASIC.pst"
+#define PS_FPGA_FILE "PS_FPGA.pst"
+
+static void get_ps_file_name(uint32_t devtype, uint32_t rom_version,
+ char *path)
+{
+ char *filename;
+
+ if (devtype == 0xdeadc0de)
+ filename = PS_ASIC_FILE;
+ else
+ filename = PS_FPGA_FILE;
+
+ snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, filename);
+}
+
+#define PATCH_FILE "RamPatch.txt"
+#define FPGA_ROM_VERSION 0x99999999
+#define ROM_DEV_TYPE 0xdeadc0de
+
+static void get_patch_file_name(uint32_t dev_type, uint32_t rom_version,
+ uint32_t build_version, char *path)
+{
+ if (rom_version == FPGA_ROM_VERSION && dev_type != ROM_DEV_TYPE &&
+ dev_type != 0 && build_version == 1)
+ path[0] = '\0';
+ else
+ snprintf(path, MAXPATHLEN, "%s%x/%s",
+ FW_PATH, rom_version, PATCH_FILE);
+}
+
+#define VERIFY_CRC 9
+#define PS_REGION 1
+#define PATCH_REGION 2
+
+static int get_ath3k_crc(int dev)
+{
+ uint8_t cmd[7];
+ uint8_t *event;
+ int err;
+
+ load_hci_ps_hdr(cmd, VERIFY_CRC, 0, PS_REGION | PATCH_REGION);
+
+ err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+ /* Send error code if CRC check patched */
+ if (read_ps_event(event, HCI_PS_CMD_OCF) >= 0)
+ err = -EILSEQ;
+
+ free(event);
+
+ return err;
+}
+
+#define DEV_REGISTER 0x4FFC
+#define GET_DEV_TYPE_OCF 0x05
+
+static int get_device_type(int dev, uint32_t *code)
+{
+ uint8_t cmd[8];
+ uint8_t *event;
+ uint32_t reg;
+ int err;
+ uint8_t *ptr = cmd;
+ hci_command_hdr *ch = (void *)cmd;
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ GET_DEV_TYPE_OCF));
+ ch->plen = 5;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ ptr[0] = (uint8_t)DEV_REGISTER;
+ ptr[1] = (uint8_t)DEV_REGISTER >> 8;
+ ptr[2] = (uint8_t)DEV_REGISTER >> 16;
+ ptr[3] = (uint8_t)DEV_REGISTER >> 24;
+ ptr[4] = 0x04;
+
+ err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, GET_DEV_TYPE_OCF);
+ if (err < 0)
+ goto cleanup;
+
+ reg = event[10];
+ reg = (reg << 8) | event[9];
+ reg = (reg << 8) | event[8];
+ reg = (reg << 8) | event[7];
+ *code = reg;
+
+cleanup:
+ free(event);
+
+ return err;
+}
+
+#define GET_VERSION_OCF 0x1E
+
+static int read_ath3k_version(int pConfig, uint32_t *rom_version,
+ uint32_t *build_version)
+{
+ uint8_t cmd[3];
+ uint8_t *event;
+ int err;
+ int status;
+ hci_command_hdr *ch = (void *)cmd;
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ GET_VERSION_OCF));
+ ch->plen = 0;
+
+ err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, GET_VERSION_OCF);
+ if (err < 0)
+ goto cleanup;
+
+ status = event[10];
+ status = (status << 8) | event[9];
+ status = (status << 8) | event[8];
+ status = (status << 8) | event[7];
+ *rom_version = status;
+
+ status = event[14];
+ status = (status << 8) | event[13];
+ status = (status << 8) | event[12];
+ status = (status << 8) | event[11];
+ *build_version = status;
+
+cleanup:
+ free(event);
+
+ return err;
+}
+
+static void convert_bdaddr(char *str_bdaddr, char *bdaddr)
+{
+ char bdbyte[3];
+ char *str_byte = str_bdaddr;
+ int i, j;
+ int colon_present = 0;
+
+ if (strstr(str_bdaddr, ":"))
+ colon_present = 1;
+
+ bdbyte[2] = '\0';
+
+ /* Reverse the BDADDR to LSB first */
+ for (i = 0, j = 5; i < 6; i++, j--) {
+ bdbyte[0] = str_byte[0];
+ bdbyte[1] = str_byte[1];
+ bdaddr[j] = strtol(bdbyte, NULL, 16);
+
+ if (colon_present == 1)
+ str_byte += 3;
+ else
+ str_byte += 2;
+ }
+}
+
+static int write_bdaddr(int pConfig, char *bdaddr)
+{
+ uint8_t *event;
+ int err;
+ uint8_t cmd[13];
+ uint8_t *ptr = cmd;
+ hci_command_hdr *ch = (void *)cmd;
+
+ memset(cmd, 0, sizeof(cmd));
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_PS_CMD_OCF));
+ ch->plen = 10;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ ptr[0] = 0x01;
+ ptr[1] = 0x01;
+ ptr[2] = 0x00;
+ ptr[3] = 0x06;
+
+ convert_bdaddr(bdaddr, (char *)&ptr[4]);
+
+ err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+ free(event);
+
+ return err;
+}
+
+#define BDADDR_FILE "ar3kbdaddr.pst"
+
+static void write_bdaddr_from_file(int rom_version, int fd)
+{
+ FILE *stream;
+ char bdaddr[PATH_MAX];
+ char bdaddr_file[PATH_MAX];
+
+ snprintf(bdaddr_file, MAXPATHLEN, "%s%x/%s",
+ FW_PATH, rom_version, BDADDR_FILE);
+
+ stream = fopen(bdaddr_file, "r");
+ if (!stream)
+ return;
+
+ if (fgets(bdaddr, PATH_MAX - 1, stream))
+ write_bdaddr(fd, bdaddr);
+
+ fclose(stream);
+}
+
+static int ath_ps_download(int fd)
+{
+ int err = 0;
+ int tag_count;
+ int patch_count = 0;
+ uint32_t rom_version = 0;
+ uint32_t build_version = 0;
+ uint32_t dev_type = 0;
+ char patch_file[PATH_MAX];
+ char ps_file[PATH_MAX];
+ FILE *stream;
+
+ /*
+ * Verfiy firmware version. depending on it select the PS
+ * config file to download.
+ */
+ if (get_device_type(fd, &dev_type) < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+
+ if (read_ath3k_version(fd, &rom_version, &build_version) < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+
+ /* Do not download configuration if CRC passes */
+ if (get_ath3k_crc(fd) < 0) {
+ err = 0;
+ goto download_cmplete;
+ }
+
+ get_ps_file_name(dev_type, rom_version, ps_file);
+ get_patch_file_name(dev_type, rom_version, build_version, patch_file);
+
+ stream = fopen(ps_file, "r");
+ if (!stream) {
+ perror("firmware file open error\n");
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+ tag_count = ath_parse_ps(stream);
+
+ fclose(stream);
+
+ if (tag_count < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+
+ /*
+ * It is not necessary that Patch file be available,
+ * continue with PS Operations if patch file is not available.
+ */
+ if (patch_file[0] == '\0')
+ err = 0;
+
+ stream = fopen(patch_file, "r");
+ if (!stream)
+ err = 0;
+ else {
+ patch_count = ps_patch_download(fd, stream);
+ fclose(stream);
+
+ if (patch_count < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+ }
+
+ err = ps_config_download(fd, tag_count);
+
+download_cmplete:
+ if (!err)
+ write_bdaddr_from_file(rom_version, fd);
+
+ return err;
+}
+
+#define HCI_SLEEP_CMD_OCF 0x04
+
+/*
+ * Atheros AR300x specific initialization post callback
+ */
+int ath3k_post(int fd, int pm)
+{
+ int dev_id, dd;
+ struct timespec tm = { 0, 50000 };
+
+ sleep(1);
+
+ dev_id = ioctl(fd, HCIUARTGETDEVICE, 0);
+ if (dev_id < 0) {
+ perror("cannot get device id");
+ return dev_id;
+ }
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("HCI device open failed");
+ return dd;
+ }
+
+ if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) {
+ perror("hci down:Power management Disabled");
+ hci_close_dev(dd);
+ return -1;
+ }
+
+ /* send vendor specific command with Sleep feature Enabled */
+ if (hci_send_cmd(dd, OGF_VENDOR_CMD, HCI_SLEEP_CMD_OCF, 1, &pm) < 0)
+ perror("PM command failed, power management Disabled");
+
+ nanosleep(&tm, NULL);
+ hci_close_dev(dd);
+
+ return 0;
+}
+
+#define HCI_VENDOR_CMD_OGF 0x3F
+#define HCI_PS_CMD_OCF 0x0B
+#define HCI_CHG_BAUD_CMD_OCF 0x0C
+
+#define WRITE_BDADDR_CMD_LEN 14
+#define WRITE_BAUD_CMD_LEN 6
+#define MAX_CMD_LEN WRITE_BDADDR_CMD_LEN
+
+static int set_cntrlr_baud(int fd, int speed)
+{
+ int baud;
+ struct timespec tm = { 0, 500000 };
+ unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE];
+ unsigned char *ptr = cmd + 1;
+ hci_command_hdr *ch = (void *)ptr;
+
+ cmd[0] = HCI_COMMAND_PKT;
+
+ /* set controller baud rate to user specified value */
+ ptr = cmd + 1;
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_CHG_BAUD_CMD_OCF));
+ ch->plen = 2;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ baud = speed/100;
+ ptr[0] = (char)baud;
+ ptr[1] = (char)(baud >> 8);
+
+ if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) {
+ perror("Failed to write change baud rate command");
+ return -ETIMEDOUT;
+ }
+
+ nanosleep(&tm, NULL);
+
+ if (read_hci_event(fd, rsp, sizeof(rsp)) < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/*
+ * Atheros AR300x specific initialization and configuration file
+ * download
+ */
+int ath3k_init(int fd, int speed, int init_speed, char *bdaddr,
+ struct termios *ti)
+{
+ int r;
+ int err = 0;
+ struct timespec tm = { 0, 500000 };
+ unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE];
+ unsigned char *ptr = cmd + 1;
+ hci_command_hdr *ch = (void *)ptr;
+
+ cmd[0] = HCI_COMMAND_PKT;
+
+ /* set both controller and host baud rate to maximum possible value */
+ err = set_cntrlr_baud(fd, speed);
+ if (err < 0)
+ return err;
+
+ err = set_speed(fd, ti, speed);
+ if (err < 0) {
+ perror("Can't set required baud rate");
+ return err;
+ }
+
+ /* Download PS and patch */
+ r = ath_ps_download(fd);
+ if (r < 0) {
+ perror("Failed to Download configuration");
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ /* Write BDADDR */
+ if (bdaddr) {
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_PS_CMD_OCF));
+ ch->plen = 10;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ ptr[0] = 0x01;
+ ptr[1] = 0x01;
+ ptr[2] = 0x00;
+ ptr[3] = 0x06;
+ str2ba(bdaddr, (bdaddr_t *)(ptr + 4));
+
+ if (write(fd, cmd, WRITE_BDADDR_CMD_LEN) !=
+ WRITE_BDADDR_CMD_LEN) {
+ perror("Failed to write BD_ADDR command\n");
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
+ perror("Failed to set BD_ADDR\n");
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+ }
+
+ /* Send HCI Reset */
+ cmd[1] = 0x03;
+ cmd[2] = 0x0C;
+ cmd[3] = 0x00;
+
+ r = write(fd, cmd, 4);
+ if (r != 4) {
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ nanosleep(&tm, NULL);
+ if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ err = set_cntrlr_baud(fd, speed);
+ if (err < 0)
+ return err;
+
+failed:
+ if (err < 0) {
+ set_cntrlr_baud(fd, init_speed);
+ set_speed(fd, ti, init_speed);
+ }
+
+ return err;
+}
diff --git a/external/cache/sources/hcitools/hciattach_bcm43xx.c b/external/cache/sources/hcitools/hciattach_bcm43xx.c
new file mode 100644
index 0000000..ad9b239
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_bcm43xx.c
@@ -0,0 +1,378 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#ifndef FIRMWARE_DIR
+#define FIRMWARE_DIR "/etc/firmware"
+#endif
+
+#define FW_EXT ".hcd"
+
+#define BCM43XX_CLOCK_48 1
+#define BCM43XX_CLOCK_24 2
+
+#define CMD_SUCCESS 0x00
+
+#define CC_MIN_SIZE 7
+
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+
+static int bcm43xx_read_local_name(int fd, char *name, size_t size)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x14, 0x0C, 0x00 };
+ unsigned char *resp;
+ unsigned int name_len;
+
+ resp = malloc(size + CC_MIN_SIZE);
+ if (!resp)
+ return -1;
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write read local name command\n");
+ goto fail;
+ }
+
+ if (read_hci_event(fd, resp, size) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to read local name, invalid HCI event\n");
+ goto fail;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to read local name, command failure\n");
+ goto fail;
+ }
+
+ name_len = resp[2] - 1;
+
+ strncpy(name, (char *) &resp[7], MIN(name_len, size));
+ name[size - 1] = 0;
+
+ free(resp);
+ return 0;
+
+fail:
+ free(resp);
+ return -1;
+}
+
+static int bcm43xx_reset(int fd)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x03, 0x0C, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write reset command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to reset chip, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to reset chip, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_set_bdaddr(int fd, const char *bdaddr)
+{
+ unsigned char cmd[] =
+ { HCI_COMMAND_PKT, 0x01, 0xfc, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ printf("Set BDADDR UART: %s\n", bdaddr);
+
+ if (str2ba(bdaddr, (bdaddr_t *) (&cmd[4])) < 0) {
+ fprintf(stderr, "Incorrect bdaddr\n");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write set bdaddr command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to set bdaddr, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to set bdaddr, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_set_speed(int fd, uint32_t speed)
+{
+ unsigned char cmd[] =
+ { HCI_COMMAND_PKT, 0x18, 0xfc, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ printf("Set Controller UART speed to %d bit/s\n", speed);
+
+ cmd[6] = (uint8_t) (speed);
+ cmd[7] = (uint8_t) (speed >> 8);
+ cmd[8] = (uint8_t) (speed >> 16);
+ cmd[9] = (uint8_t) (speed >> 24);
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write update baudrate command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to update baudrate, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to update baudrate, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_set_clock(int fd, unsigned char clock)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x45, 0xfc, 0x01, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ printf("Set Controller clock (%d)\n", clock);
+
+ cmd[4] = clock;
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write update clock command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to update clock, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to update clock, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_load_firmware(int fd, const char *fw)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x2e, 0xfc, 0x00 };
+ struct timespec tm_mode = { 0, 50000 };
+ struct timespec tm_ready = { 0, 2000000 };
+ unsigned char resp[CC_MIN_SIZE];
+ unsigned char tx_buf[1024];
+ int len, fd_fw, n;
+
+ printf("Flash firmware %s\n", fw);
+
+ fd_fw = open(fw, O_RDONLY);
+ if (fd_fw < 0) {
+ fprintf(stderr, "Unable to open firmware (%s)\n", fw);
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write download mode command\n");
+ goto fail;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to load firmware, invalid HCI event\n");
+ goto fail;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to load firmware, command failure\n");
+ goto fail;
+ }
+
+ /* Wait 50ms to let the firmware placed in download mode */
+ nanosleep(&tm_mode, NULL);
+
+ tcflush(fd, TCIOFLUSH);
+
+ while ((n = read(fd_fw, &tx_buf[1], 3))) {
+ if (n < 0) {
+ fprintf(stderr, "Failed to read firmware\n");
+ goto fail;
+ }
+
+ tx_buf[0] = HCI_COMMAND_PKT;
+
+ len = tx_buf[3];
+
+ if (read(fd_fw, &tx_buf[4], len) < 0) {
+ fprintf(stderr, "Failed to read firmware\n");
+ goto fail;
+ }
+
+ if (write(fd, tx_buf, len + 4) != (len + 4)) {
+ fprintf(stderr, "Failed to write firmware\n");
+ goto fail;
+ }
+
+ read_hci_event(fd, resp, sizeof(resp));
+ tcflush(fd, TCIOFLUSH);
+ }
+
+ /* Wait for firmware ready */
+ nanosleep(&tm_ready, NULL);
+
+ close(fd_fw);
+ return 0;
+
+fail:
+ close(fd_fw);
+ return -1;
+}
+
+static int bcm43xx_locate_patch(const char *dir_name,
+ const char *chip_name, char *location)
+{
+ DIR *dir;
+ int ret = -1;
+
+ dir = opendir(dir_name);
+ if (!dir) {
+ fprintf(stderr, "Cannot open directory '%s': %s\n",
+ dir_name, strerror(errno));
+ return -1;
+ }
+
+ /* Recursively look for a BCM43XX*.hcd */
+ while (1) {
+ struct dirent *entry = readdir(dir);
+ if (!entry)
+ break;
+
+ if (entry->d_type & DT_DIR) {
+ char path[PATH_MAX];
+
+ if (!strcmp(entry->d_name, "..") || !strcmp(entry->d_name, "."))
+ continue;
+
+ snprintf(path, PATH_MAX, "%s/%s", dir_name, entry->d_name);
+
+ ret = bcm43xx_locate_patch(path, chip_name, location);
+ if (!ret)
+ break;
+ } else if (!strncmp(chip_name, entry->d_name, strlen(chip_name))) {
+ unsigned int name_len = strlen(entry->d_name);
+ size_t curs_ext = name_len - sizeof(FW_EXT) + 1;
+
+ if (curs_ext > name_len)
+ break;
+
+ if (strncmp(FW_EXT, &entry->d_name[curs_ext], sizeof(FW_EXT)))
+ break;
+
+ /* found */
+ snprintf(location, PATH_MAX, "%s/%s", dir_name, entry->d_name);
+ ret = 0;
+ break;
+ }
+ }
+
+ closedir(dir);
+
+ return ret;
+}
+
+int bcm43xx_init(int fd, int speed, struct termios *ti, const char *bdaddr)
+{
+ char chip_name[20];
+ char fw_path[PATH_MAX];
+
+ printf("bcm43xx_init\n");
+
+ if (bcm43xx_reset(fd))
+ return -1;
+
+ if (bcm43xx_read_local_name(fd, chip_name, sizeof(chip_name)))
+ return -1;
+
+ if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
+ fprintf(stderr, "Patch not found, continue anyway\n");
+ } else {
+ if (bcm43xx_load_firmware(fd, fw_path))
+ return -1;
+
+ if (bcm43xx_reset(fd))
+ return -1;
+ }
+
+ if (bdaddr)
+ bcm43xx_set_bdaddr(fd, bdaddr);
+
+ if (speed > 3000000 && bcm43xx_set_clock(fd, BCM43XX_CLOCK_48))
+ return -1;
+
+ if (bcm43xx_set_speed(fd, speed))
+ return -1;
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_intel.c b/external/cache/sources/hcitools/hciattach_intel.c
new file mode 100644
index 0000000..749098e
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_intel.c
@@ -0,0 +1,595 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#ifdef INTEL_DEBUG
+#define DBGPRINT(fmt, args...) printf("DBG: " fmt "\n", ## args)
+#define PRINT_PACKET(buf, len, msg) { \
+ int i; \
+ printf("%s\n", msg); \
+ for (i = 0; i < len; i++) \
+ printf("%02X ", buf[i]); \
+ printf("\n"); \
+ }
+#else
+#define DBGPRINT(fmt, args...)
+#define PRINT_PACKET(buf, len, msg)
+#endif
+
+#define PATCH_SEQ_EXT ".bseq"
+#define PATCH_FILE_PATH "/lib/firmware/intel/"
+#define PATCH_MAX_LEN 260
+#define PATCH_TYPE_CMD 1
+#define PATCH_TYPE_EVT 2
+
+#define INTEL_VER_PARAM_LEN 9
+#define INTEL_MFG_PARAM_LEN 2
+
+/**
+ * A data structure for a patch entry.
+ */
+struct patch_entry {
+ int type;
+ int len;
+ unsigned char data[PATCH_MAX_LEN];
+};
+
+/**
+ * A structure for patch context
+ */
+struct patch_ctx {
+ int dev;
+ int fd;
+ int patch_error;
+ int reset_enable_patch;
+};
+
+/**
+ * Send HCI command to the controller
+ */
+static int intel_write_cmd(int dev, unsigned char *buf, int len)
+{
+ int ret;
+
+ PRINT_PACKET(buf, len, "<----- SEND CMD: ");
+
+ ret = write(dev, buf, len);
+ if (ret < 0)
+ return -errno;
+
+ if (ret != len)
+ return -1;
+
+ return ret;
+}
+
+/**
+ * Read the event from the controller
+ */
+static int intel_read_evt(int dev, unsigned char *buf, int len)
+{
+ int ret;
+
+ ret = read_hci_event(dev, buf, len);
+ if (ret < 0)
+ return -1;
+
+ PRINT_PACKET(buf, ret, "-----> READ EVT: ");
+
+ return ret;
+}
+
+/**
+ * Validate HCI events
+ */
+static int validate_events(struct patch_entry *event,
+ struct patch_entry *entry)
+{
+ if (event == NULL || entry == NULL) {
+ DBGPRINT("invalid patch entry parameters");
+ return -1;
+ }
+
+ if (event->len != entry->len) {
+ DBGPRINT("lengths are mismatched:[%d|%d]",
+ event->len, entry->len);
+ return -1;
+ }
+
+ if (memcmp(event->data, entry->data, event->len)) {
+ DBGPRINT("data is mismatched");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Read the next patch entry one line at a time
+ */
+static int get_next_patch_entry(int fd, struct patch_entry *entry)
+{
+ int size;
+ char rb;
+
+ if (read(fd, &rb, 1) <= 0)
+ return 0;
+
+ entry->type = rb;
+
+ switch (entry->type) {
+ case PATCH_TYPE_CMD:
+ entry->data[0] = HCI_COMMAND_PKT;
+
+ if (read(fd, &entry->data[1], 3) < 0)
+ return -1;
+
+ size = (int)entry->data[3];
+
+ if (read(fd, &entry->data[4], size) < 0)
+ return -1;
+
+ entry->len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + size;
+
+ break;
+
+ case PATCH_TYPE_EVT:
+ entry->data[0] = HCI_EVENT_PKT;
+
+ if (read(fd, &entry->data[1], 2) < 0)
+ return -1;
+
+ size = (int)entry->data[2];
+
+ if (read(fd, &entry->data[3], size) < 0)
+ return -1;
+
+ entry->len = HCI_TYPE_LEN + HCI_EVENT_HDR_SIZE + size;
+
+ break;
+
+ default:
+ fprintf(stderr, "invalid patch entry(%d)\n", entry->type);
+ return -1;
+ }
+
+ return entry->len;
+}
+
+/**
+ * Download the patch set to the controller and verify the event
+ */
+static int intel_download_patch(struct patch_ctx *ctx)
+{
+ int ret;
+ struct patch_entry entry;
+ struct patch_entry event;
+
+ DBGPRINT("start patch downloading");
+
+ do {
+ ret = get_next_patch_entry(ctx->fd, &entry);
+ if (ret <= 0) {
+ ctx->patch_error = 1;
+ break;
+ }
+
+ switch (entry.type) {
+ case PATCH_TYPE_CMD:
+ ret = intel_write_cmd(ctx->dev,
+ entry.data,
+ entry.len);
+ if (ret <= 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n",
+ ret);
+ return ret;
+ }
+ break;
+
+ case PATCH_TYPE_EVT:
+ ret = intel_read_evt(ctx->dev, event.data,
+ sizeof(event.data));
+ if (ret <= 0) {
+ fprintf(stderr, "failed to read evt(%d)\n",
+ ret);
+ return ret;
+ }
+ event.len = ret;
+
+ if (validate_events(&event, &entry) < 0) {
+ DBGPRINT("events are mismatched");
+ ctx->patch_error = 1;
+ return -1;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "unknown patch type(%d)\n",
+ entry.type);
+ return -1;
+ }
+ } while (1);
+
+ return ret;
+}
+
+static int open_patch_file(struct patch_ctx *ctx, char *fw_ver)
+{
+ char patch_file[PATH_MAX];
+
+ snprintf(patch_file, PATH_MAX, "%s%s%s", PATCH_FILE_PATH,
+ fw_ver, PATCH_SEQ_EXT);
+ DBGPRINT("PATCH_FILE: %s", patch_file);
+
+ ctx->fd = open(patch_file, O_RDONLY);
+ if (ctx->fd < 0) {
+ DBGPRINT("cannot open patch file. go to post patch");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Prepare the controller for patching.
+ */
+static int pre_patch(struct patch_ctx *ctx)
+{
+ int ret, i;
+ struct patch_entry entry;
+ char fw_ver[INTEL_VER_PARAM_LEN * 2];
+
+ DBGPRINT("start pre_patch");
+
+ entry.data[0] = HCI_COMMAND_PKT;
+ entry.data[1] = 0x11;
+ entry.data[2] = 0xFC;
+ entry.data[3] = 0x02;
+ entry.data[4] = 0x01;
+ entry.data[5] = 0x00;
+ entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + INTEL_MFG_PARAM_LEN;
+
+ ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+
+ if (entry.data[6] != 0x00) {
+ DBGPRINT("command failed. status=%02x", entry.data[6]);
+ ctx->patch_error = 1;
+ return -1;
+ }
+
+ entry.data[0] = HCI_COMMAND_PKT;
+ entry.data[1] = 0x05;
+ entry.data[2] = 0xFC;
+ entry.data[3] = 0x00;
+ entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE;
+
+ ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+
+ if (entry.data[6] != 0x00) {
+ DBGPRINT("command failed. status=%02x", entry.data[6]);
+ ctx->patch_error = 1;
+ return -1;
+ }
+
+ for (i = 0; i < INTEL_VER_PARAM_LEN; i++)
+ sprintf(&fw_ver[i*2], "%02x", entry.data[7+i]);
+
+ if (open_patch_file(ctx, fw_ver) < 0) {
+ ctx->patch_error = 1;
+ return -1;
+ }
+
+ return ret;
+}
+
+/*
+ * check the event is startup event
+ */
+static int is_startup_evt(unsigned char *buf)
+{
+ if (buf[1] == 0xFF && buf[2] == 0x01 && buf[3] == 0x00)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Finalize the patch process and reset the controller
+ */
+static int post_patch(struct patch_ctx *ctx)
+{
+ int ret;
+ struct patch_entry entry;
+
+ DBGPRINT("start post_patch");
+
+ entry.data[0] = HCI_COMMAND_PKT;
+ entry.data[1] = 0x11;
+ entry.data[2] = 0xFC;
+ entry.data[3] = 0x02;
+ entry.data[4] = 0x00;
+ if (ctx->reset_enable_patch)
+ entry.data[5] = 0x02;
+ else
+ entry.data[5] = 0x01;
+
+ entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + INTEL_MFG_PARAM_LEN;
+
+ ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+
+ if (entry.data[6] != 0x00) {
+ fprintf(stderr, "cmd failed. st=%02x\n", entry.data[6]);
+ return -1;
+ }
+
+ do {
+ ret = intel_read_evt(ctx->dev, entry.data,
+ sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read cmd(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+ } while (!is_startup_evt(entry.data));
+
+ return ret;
+}
+
+/**
+ * Main routine that handles the device patching process.
+ */
+static int intel_patch_device(struct patch_ctx *ctx)
+{
+ int ret;
+
+ ret = pre_patch(ctx);
+ if (ret < 0) {
+ if (!ctx->patch_error) {
+ fprintf(stderr, "I/O error: pre_patch failed\n");
+ return ret;
+ }
+
+ DBGPRINT("patch failed. proceed to post patch");
+ goto post_patch;
+ }
+
+ ret = intel_download_patch(ctx);
+ if (ret < 0) {
+ if (!ctx->patch_error) {
+ fprintf(stderr, "I/O error: download_patch failed\n");
+ close(ctx->fd);
+ return ret;
+ }
+ } else {
+ DBGPRINT("patch done");
+ ctx->reset_enable_patch = 1;
+ }
+
+ close(ctx->fd);
+
+post_patch:
+ ret = post_patch(ctx);
+ if (ret < 0) {
+ fprintf(stderr, "post_patch failed(%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int set_rts(int dev, int rtsval)
+{
+ int arg;
+
+ if (ioctl(dev, TIOCMGET, &arg) < 0) {
+ perror("cannot get TIOCMGET");
+ return -errno;
+ }
+ if (rtsval)
+ arg |= TIOCM_RTS;
+ else
+ arg &= ~TIOCM_RTS;
+
+ if (ioctl(dev, TIOCMSET, &arg) == -1) {
+ perror("cannot set TIOCMGET");
+ return -errno;
+ }
+
+ return 0;
+}
+
+static unsigned char get_intel_speed(int speed)
+{
+ switch (speed) {
+ case 9600:
+ return 0x00;
+ case 19200:
+ return 0x01;
+ case 38400:
+ return 0x02;
+ case 57600:
+ return 0x03;
+ case 115200:
+ return 0x04;
+ case 230400:
+ return 0x05;
+ case 460800:
+ return 0x06;
+ case 921600:
+ return 0x07;
+ case 1843200:
+ return 0x08;
+ case 3250000:
+ return 0x09;
+ case 2000000:
+ return 0x0A;
+ case 3000000:
+ return 0x0B;
+ default:
+ return 0xFF;
+ }
+}
+
+/**
+ * if it failed to change to new baudrate, it will rollback
+ * to initial baudrate
+ */
+static int change_baudrate(int dev, int init_speed, int *speed,
+ struct termios *ti)
+{
+ int ret;
+ unsigned char br;
+ unsigned char cmd[5];
+ unsigned char evt[7];
+
+ DBGPRINT("start baudrate change");
+
+ ret = set_rts(dev, 0);
+ if (ret < 0) {
+ fprintf(stderr, "failed to clear RTS\n");
+ return ret;
+ }
+
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x06;
+ cmd[2] = 0xFC;
+ cmd[3] = 0x01;
+
+ br = get_intel_speed(*speed);
+ if (br == 0xFF) {
+ fprintf(stderr, "speed %d is not supported\n", *speed);
+ return -1;
+ }
+ cmd[4] = br;
+
+ ret = intel_write_cmd(dev, cmd, sizeof(cmd));
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ /*
+ * wait for buffer to be consumed by the controller
+ */
+ usleep(300000);
+
+ if (set_speed(dev, ti, *speed) < 0) {
+ fprintf(stderr, "can't set to new baud rate\n");
+ return -1;
+ }
+
+ ret = set_rts(dev, 1);
+ if (ret < 0) {
+ fprintf(stderr, "failed to set RTS\n");
+ return ret;
+ }
+
+ ret = intel_read_evt(dev, evt, sizeof(evt));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+
+ if (evt[4] != 0x00) {
+ fprintf(stderr,
+ "failed to change speed. use default speed %d\n",
+ init_speed);
+ *speed = init_speed;
+ }
+
+ return 0;
+}
+
+/**
+ * An entry point for Intel specific initialization
+ */
+int intel_init(int dev, int init_speed, int *speed, struct termios *ti)
+{
+ int ret = 0;
+ struct patch_ctx ctx;
+
+ if (change_baudrate(dev, init_speed, speed, ti) < 0)
+ return -1;
+
+ ctx.dev = dev;
+ ctx.patch_error = 0;
+ ctx.reset_enable_patch = 0;
+
+ ret = intel_patch_device(&ctx);
+ if (ret < 0)
+ fprintf(stderr, "failed to initialize the device");
+
+ return ret;
+}
diff --git a/external/cache/sources/hcitools/hciattach_qualcomm.c b/external/cache/sources/hcitools/hciattach_qualcomm.c
new file mode 100644
index 0000000..0e02e1e
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_qualcomm.c
@@ -0,0 +1,273 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#define FAILIF(x, args...) do { \
+ if (x) { \
+ fprintf(stderr, ##args); \
+ return -1; \
+ } \
+} while (0)
+
+typedef struct {
+ uint8_t uart_prefix;
+ hci_event_hdr hci_hdr;
+ evt_cmd_complete cmd_complete;
+ uint8_t status;
+ uint8_t data[16];
+} __attribute__((packed)) command_complete_t;
+
+static int read_command_complete(int fd,
+ unsigned short opcode,
+ unsigned char len)
+{
+ command_complete_t resp;
+ unsigned char vsevent[512];
+ int n;
+
+ /* Read reply. */
+ n = read_hci_event(fd, vsevent, sizeof(vsevent));
+ FAILIF(n < 0, "Failed to read response");
+
+ FAILIF(vsevent[1] != 0xFF, "Failed to read response");
+
+ n = read_hci_event(fd, (unsigned char *)&resp, sizeof(resp));
+ FAILIF(n < 0, "Failed to read response");
+
+ /* event must be event-complete */
+ FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE,
+ "Error in response: not a cmd-complete event, "
+ "but 0x%02x!\n", resp.hci_hdr.evt);
+
+ FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */
+ "Error in response: plen is not >= 4, but 0x%02x!\n",
+ resp.hci_hdr.plen);
+
+ /* cmd-complete event: opcode */
+ FAILIF(resp.cmd_complete.opcode != 0,
+ "Error in response: opcode is 0x%04x, not 0!",
+ resp.cmd_complete.opcode);
+
+ return resp.status == 0 ? 0 : -1;
+}
+
+static int qualcomm_load_firmware(int fd, const char *firmware, const char *bdaddr_s)
+{
+
+ int fw = open(firmware, O_RDONLY);
+
+ fprintf(stdout, "Opening firmware file: %s\n", firmware);
+
+ FAILIF(fw < 0,
+ "Could not open firmware file %s: %s (%d).\n",
+ firmware, strerror(errno), errno);
+
+ fprintf(stdout, "Uploading firmware...\n");
+ do {
+ /* Read each command and wait for a response. */
+ unsigned char data[1024];
+ unsigned char cmdp[1 + sizeof(hci_command_hdr)];
+ hci_command_hdr *cmd = (hci_command_hdr *) (cmdp + 1);
+ int nr;
+
+ nr = read(fw, cmdp, sizeof(cmdp));
+ if (!nr)
+ break;
+
+ FAILIF(nr != sizeof(cmdp),
+ "Could not read H4 + HCI header!\n");
+ FAILIF(*cmdp != HCI_COMMAND_PKT,
+ "Command is not an H4 command packet!\n");
+
+ FAILIF(read(fw, data, cmd->plen) != cmd->plen,
+ "Could not read %d bytes of data \
+ for command with opcode %04x!\n",
+ cmd->plen, cmd->opcode);
+
+ if ((data[0] == 1) && (data[1] == 2) && (data[2] == 6)) {
+ bdaddr_t bdaddr;
+ if (bdaddr_s != NULL) {
+ str2ba(bdaddr_s, &bdaddr);
+ memcpy(&data[3], &bdaddr, sizeof(bdaddr_t));
+ }
+ }
+
+ {
+ int nw;
+ struct iovec iov_cmd[2];
+ iov_cmd[0].iov_base = cmdp;
+ iov_cmd[0].iov_len = sizeof(cmdp);
+ iov_cmd[1].iov_base = data;
+ iov_cmd[1].iov_len = cmd->plen;
+ nw = writev(fd, iov_cmd, 2);
+ FAILIF(nw != (int) sizeof(cmdp) + cmd->plen,
+ "Could not send entire command \
+ (sent only %d bytes)!\n",
+ nw);
+ }
+
+ /* Wait for response */
+ if (read_command_complete(fd, cmd->opcode, cmd->plen) < 0)
+ return -1;
+ } while (1);
+ fprintf(stdout, "Firmware upload successful.\n");
+
+ close(fw);
+
+ return 0;
+}
+
+int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+ unsigned char resp[100]; /* Response */
+ char fw[100];
+ int n;
+
+ memset(resp, 0, 100);
+
+ /* Get Manufacturer and LMP version */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 4) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response");
+ return -1;
+ }
+
+ /* Wait for command complete event for our Opcode */
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ /* Verify manufacturer */
+ if ((resp[11] & 0xFF) != 0x1d)
+ fprintf(stderr,
+ "WARNING : module's manufacturer is not Qualcomm\n");
+
+ /* Print LMP version */
+ fprintf(stderr,
+ "Qualcomm module LMP version : 0x%02x\n", resp[10] & 0xFF);
+
+ /* Print LMP subversion */
+ {
+ unsigned short lmp_subv = resp[13] | (resp[14] << 8);
+
+ fprintf(stderr, "Qualcomm module LMP sub-version : 0x%04x\n",
+ lmp_subv);
+ }
+
+ /* Get SoC type */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x00;
+ cmd[2] = 0xFC;
+ cmd[3] = 0x01;
+ cmd[4] = 0x06;
+
+ do {
+ n = write(fd, cmd, 5);
+ if (n < 5) {
+ perror("Failed to write vendor init command");
+ return -1;
+ }
+
+ /* Read reply. */
+ if ((n = read_hci_event(fd, resp, 100)) < 0) {
+ perror("Failed to read vendor init response");
+ return -1;
+ }
+
+ } while (resp[3] != 0 && resp[4] != 2);
+
+ snprintf(fw, sizeof(fw), "/etc/firmware/%c%c%c%c%c%c_%c%c%c%c.bin",
+ resp[18], resp[19], resp[20], resp[21],
+ resp[22], resp[23],
+ resp[32], resp[33], resp[34], resp[35]);
+
+ /* Wait for command complete event for our Opcode */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response");
+ return -1;
+ }
+
+ qualcomm_load_firmware(fd, fw, bdaddr);
+
+ /* Reset */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x03;
+ cmd[2] = 0x0C;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 4) {
+ perror("Failed to write reset command");
+ return -1;
+ }
+
+ /* Read reply. */
+ if ((n = read_hci_event(fd, resp, 100)) < 0) {
+ perror("Failed to read reset response");
+ return -1;
+ }
+
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ nanosleep(&tm, NULL);
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_rtk.c b/external/cache/sources/hcitools/hciattach_rtk.c
new file mode 100644
index 0000000..6739406
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_rtk.c
@@ -0,0 +1,2563 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ * Copyright (C) 2013-2014 Realtek Semiconductor Corp.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#define Config_Android 0 /*1 for android; 0 for Linux*/
+
+#if Config_Android //for Android
+#include
+#include
+#include
+#else //for Linux
+#include
+#include
+#include
+#include
+#include
+#endif
+
+#include "hciattach.h"
+
+#define BAUDRATE_4BYTES
+#define RTK_VERSION "2.3"
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_le16(d) (d)
+#define cpu_to_le32(d) (d)
+#define le16_to_cpu(d) (d)
+#define le32_to_cpu(d) (d)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_le16(d) bswap_16(d)
+#define cpu_to_le32(d) bswap_32(d)
+#define le16_to_cpu(d) bswap_16(d)
+#define le32_to_cpu(d) bswap_32(d)
+#else
+#error "Unknown byte order"
+#endif
+
+/* log related */
+#define LOG_STR "Realtek Bluetooth"
+#define DBG_ON 1
+
+#define RS_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n", LOG_STR, ##arg); \
+ } while (0)
+
+#define RS_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror("reason: "); \
+ } while (0)
+
+#define RS_DUMP(buffer, len) \
+ do { \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ for (int i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+struct sk_buff {
+ uint32_t max_len;
+ uint32_t data_len;
+ uint8_t data[0];
+};
+
+/* Skb helpers */
+struct bt_skb_cb {
+ uint8_t pkt_type;
+ uint8_t incoming;
+ uint16_t expect;
+ uint8_t tx_seq;
+ uint8_t retries;
+ uint8_t sar;
+ uint16_t channel;
+};
+
+typedef struct {
+ uint8_t index;
+ uint8_t data[252];
+} __attribute__ ((packed)) download_vendor_patch_cp;
+
+struct hci_command_hdr {
+ uint16_t opcode; /* OCF & OGF */
+ uint8_t plen;
+} __attribute__ ((packed));
+
+struct hci_event_hdr {
+ uint8_t evt;
+ uint8_t plen;
+} __attribute__ ((packed));
+
+struct hci_ev_cmd_complete {
+ uint8_t ncmd;
+ uint16_t opcode;
+} __attribute__ ((packed));
+
+#define HCI_COMMAND_HDR_SIZE 3
+#define HCI_EVENT_HDR_SIZE 2
+
+#define HCI_CMD_READ_BD_ADDR 0x1009
+#define HCI_VENDOR_CHANGE_BDRATE 0xfc17
+#define HCI_VENDOR_READ_RTK_ROM_VERISION 0xfc6d
+#define HCI_VENDOR_READ_LMP_VERISION 0x1001
+#define HCI_VENDOR_READ_CHIP_TYPE 0xfc61
+
+#define ROM_LMP_8723a 0x1200
+
+#define RTK_VENDOR_CONFIG_MAGIC 0x8723ab55
+
+#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
+
+#if Config_Android
+#define FIRMWARE_DIRECTORY "/system/vendor/etc/firmware"
+#define BT_CONFIG_DIRECTORY "/system/vendor/etc/firmware"
+#else
+#define FIRMWARE_DIRECTORY "/system/vendor/etc/firmware"
+#define BT_CONFIG_DIRECTORY "/system/vendor/etc/firmware"
+#endif
+
+#define BT_ADDR_DIR "/data/misc/bluetooth/"
+#define BT_ADDR_FILE "/data/misc/bluetooth/btmac.txt"
+
+#define PATCH_DATA_FIELD_MAX_SIZE 252
+#define READ_DATA_SIZE 16
+
+/* HCI data types */
+#define H5_ACK_PKT 0x00
+#define HCI_COMMAND_PKT 0x01
+#define HCI_ACLDATA_PKT 0x02
+#define HCI_SCODATA_PKT 0x03
+#define HCI_EVENT_PKT 0x04
+#define H5_VDRSPEC_PKT 0x0E
+#define H5_LINK_CTL_PKT 0x0F
+
+
+#define HCI_VERSION_MASK_10 (1<<0) // Bluetooth Core Spec 1.0b
+#define HCI_VERSION_MASK_11 (1<<1) // Bluetooth Core Spec 1.1
+#define HCI_VERSION_MASK_12 (1<<2) // Bluetooth Core Spec 1.2
+#define HCI_VERSION_MASK_20 (1<<3) // Bluetooth Core Spec 2.0+EDR
+#define HCI_VERSION_MASK_21 (1<<4) // Bluetooth Core Spec 2.1+EDR
+#define HCI_VERSION_MASK_30 (1<<5) // Bluetooth Core Spec 3.0+HS
+#define HCI_VERSION_MASK_40 (1<<6) // Bluetooth Core Spec 4.0
+#define HCI_VERSION_MASK_41 (1<<7) // Bluetooth Core Spec 4.1
+#define HCI_VERSION_MASK_42 (1<<8) // Bluetooth Core Spec 4.2
+#define HCI_VERSION_MASK_ALL (0xFFFFFFFF)
+
+#define HCI_REVISION_MASK_ALL (0xFFFFFFFF)
+
+#define LMP_SUBVERSION_NONE (0x0)
+
+#define CHIPTYPE_NONE (0x1F) // Chip Type's range: 0x0 ~ 0xF
+#define CHIP_TYPE_MASK_ALL (0xFFFFFFFF)
+
+#define PROJECT_ID_MASK_ALL (0xFFFFFFFF) // temp used for unknow project id for a new chip
+
+#define CONFIG_MAC_OFFSET_GEN_1_2 (0x3C) // MAC's OFFSET in config/efuse for realtek generation 1~2 bluetooth chip
+#define CONFIG_MAC_OFFSET_GEN_3PLUS (0x44) // MAC's OFFSET in config/efuse for rtk generation 3+ bluetooth chip
+#define CONFIG_MAC_OFFSET_GEN_4PLUS (0x30) // MAC's OFFSET in config/efuse for rtk generation 4+ bluetooth chip
+
+#define PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE (0x1)
+
+#define MAX_PATCH_SIZE_24K (1024*24) // 24K
+#define MAX_PATCH_SIZE_40K (1024*40) // 40K
+
+struct rtk_bt_vendor_config_entry {
+ uint16_t offset;
+ uint8_t entry_len;
+ uint8_t entry_data[0];
+} __attribute__ ((packed));
+
+struct rtk_bt_vendor_config {
+ uint32_t signature;
+ uint16_t data_len;
+ struct rtk_bt_vendor_config_entry entry[0];
+} __attribute__ ((packed));
+
+struct rtk_epatch_entry {
+ uint16_t chipID;
+ uint16_t patch_length;
+ uint32_t start_offset;
+} __attribute__ ((packed));
+
+struct rtk_epatch {
+ uint8_t signature[8];
+ uint32_t fm_version;
+ uint16_t number_of_total_patch;
+ struct rtk_epatch_entry entry[0];
+} __attribute__ ((packed));
+
+typedef enum _RTK_ROM_VERSION_CMD_STATE {
+ cmd_not_send,
+ cmd_has_sent,
+ event_received
+} RTK_ROM_VERSION_CMD_STATE;
+
+#pragma pack(1)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+typedef struct _H5_PKT_HEADER {
+ uint8_t SeqNumber:3;
+ uint8_t AckNumber:3;
+ uint8_t DicPresent:1; /* Data Integrity Check Present */
+ uint8_t ReliablePkt:1;
+ uint16_t PktType:4;
+ uint16_t PayloadLen:12;
+ uint8_t HdrChecksum;
+} H5_PKT_HEADER;
+#else
+typedef struct _H5_PKT_HEADER {
+ uint8_t ReliablePkt:1;
+ uint8_t DicPresent:1; /* Data Integrity Check Present */
+ uint8_t AckNumber:3;
+ uint8_t SeqNumber:3;
+ uint16_t PayloadLen:12;
+ uint16_t PktType:4;
+ uint8_t HdrChecksum;
+} H5_PKT_HEADER;
+#endif
+
+typedef enum _H5_RX_STATE {
+ H5_W4_PKT_DELIMITER,
+ H5_W4_PKT_START,
+ H5_W4_HDR,
+ H5_W4_DATA,
+ H5_W4_CRC
+} H5_RX_STATE;
+
+typedef enum _H5_RX_ESC_STATE {
+ H5_ESCSTATE_NOESC,
+ H5_ESCSTATE_ESC
+} H5_RX_ESC_STATE;
+
+typedef enum _H5_LINK_STATE {
+ H5_SYNC,
+ H5_CONFIG,
+ H5_INIT,
+ H5_PATCH,
+ H5_ACTIVE
+} H5_LINK_STATE;
+
+typedef enum _PATCH_PROTOCOL {
+ PATCH_PROTOCAL_H4,
+ PATCH_PROTOCAL_H5
+} PATCH_PROTOCOL;
+
+struct rtk_h5_struct {
+ uint8_t rxseq_txack; /* rxseq == txack. expected rx SeqNumber */
+ uint8_t rxack; /* Last packet sent by us that the peer ack'ed */
+ uint8_t use_crc;
+ uint8_t is_txack_req; /* txack required? Do we need to send ack's to the peer? */
+ /* Reliable packet sequence number - used to assign seq to each rel pkt. */
+ uint8_t msgq_txseq; /* next pkt seq */
+ uint16_t message_crc;
+ uint32_t rx_count; /* expected pkts to recv */
+ H5_RX_STATE rx_state;
+ H5_RX_ESC_STATE rx_esc_state;
+ H5_LINK_STATE link_estab_state;
+ struct sk_buff *rx_skb;
+ struct sk_buff *host_last_cmd;
+};
+
+struct patch_struct {
+ int nTxIndex; /* current sending pkt number */
+ int nTotal; /* total pkt number */
+ int nRxIndex; /* ack index from board */
+ int nNeedRetry; /* if no response from board */
+};
+
+typedef struct {
+ uint16_t lmp_subversion;
+ uint32_t hci_version_mask;
+ uint32_t hci_revision_mask;
+ uint32_t chip_type_mask;
+ uint32_t project_id_mask;
+ char *patch_name;
+ char *config_name;
+ uint16_t mac_offset;
+ uint32_t max_patch_size;
+} patch_info;
+
+/* h/w config control block */
+typedef struct {
+ uint32_t max_patch_size;
+ uint32_t baudrate;
+ uint16_t lmp_subversion;
+ uint16_t lmp_subversion_default;
+ uint16_t lmp_sub_current;
+ uint8_t state; /* Hardware configuration state */
+ uint8_t eversion;
+ uint32_t project_id_mask;
+ uint8_t hci_version;
+ uint8_t hci_revision;
+ uint8_t chip_type;
+} bt_hw_cfg_cb_t;
+
+static patch_info patch_table[] = {
+/* lmp_subv hci_version_mask hci_revision_mask chip_type_mask project_id_mask fw name config name mac offset max_patch_size */
+ {0x1200, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<0, "rtl8723as_fw", "rtl8723as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723AS
+#ifdef RTL_8723BS_BT_USED
+ {0x8723, ~(HCI_VERSION_MASK_21), ~(1<<0xd), CHIP_TYPE_MASK_ALL, 1<<1, "rtl8723bs_fw", "rtl8723bs_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723BS
+#else
+ {0x8723, ~(HCI_VERSION_MASK_21), ~(1<<0xd), CHIP_TYPE_MASK_ALL, 1<<1, "rtl8723bs_VQ0_fw", "rtl8723bs_VQ0_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723BS_VQ0
+#endif
+ {0x8821, HCI_VERSION_MASK_ALL, ~(1<<0xc), CHIP_TYPE_MASK_ALL, 1<<2, "rtl8821as_fw", "rtl8821as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8821AS
+/* {0x8761, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<3, "rtl8761at_fw", "rtl8761at_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8761AW */
+ {0x8761, HCI_VERSION_MASK_ALL, ~(1<<0xb), CHIP_TYPE_MASK_ALL, 1<<3, "rtl8761at_fw", "rtl8761at_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8761AW
+ {0x8761, HCI_VERSION_MASK_ALL, (1<<0xb), CHIP_TYPE_MASK_ALL, 1<<14, "rtl8761bt_fw", "rtl8761bt_config", CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, //Rtl8761BW
+
+ {0x8723, HCI_VERSION_MASK_21, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<4, "rtl8703as_fw", "rtl8703as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8703AS
+
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<7, 1<<6, "rtl8703bs_fw", "rtl8703bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8703BS
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<5, 1<<7, "rtl8723cs_xx_fw", "rtl8723cs_xx_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_xx
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<3, 1<<7, "rtl8723cs_cg_fw", "rtl8723cs_cg_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_cg
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<4, 1<<7, "rtl8723cs_vf_fw", "rtl8723cs_vf_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_vf
+/* {0x8822, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<8, "rtl8822bs_fw", "rtl8822bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8822BS */
+ {0x8822, HCI_VERSION_MASK_ALL, ~(1<<0xc), CHIP_TYPE_MASK_ALL, 1<<8, "rtl8822bs_fw", "rtl8822bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8822BS
+ {0x8822, HCI_VERSION_MASK_ALL, (1<<0xc), CHIP_TYPE_MASK_ALL, 1<<13, "rtl8822cs_fw", "rtl8822cs_config", CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, //Rtl8822CS
+
+ {0x8723, HCI_VERSION_MASK_ALL, (1<<0xd), ~(1<<7), 1<<9, "rtl8723ds_fw", "rtl8723ds_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //Rtl8723ds
+ {0x8723, HCI_VERSION_MASK_ALL, (1<<0xd), 1<<7, 1<<9, "rtl8703cs_fw", "rtl8703cs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //Rtl8703cs
+ {0x8821, HCI_VERSION_MASK_ALL, (1<<0xc), CHIP_TYPE_MASK_ALL, 1<<10, "rtl8821cs_fw", "rtl8821cs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //RTL8821CS
+/* todo: RTL8703CS */
+ {LMP_SUBVERSION_NONE, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, PROJECT_ID_MASK_ALL, "rtl_none_fw", "rtl_none_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}
+};
+
+static bt_hw_cfg_cb_t hw_cfg_cb;
+static uint8_t gEVersion;
+static RTK_ROM_VERSION_CMD_STATE gRom_version_cmd_state;
+static RTK_ROM_VERSION_CMD_STATE ghci_version_cmd_state;
+static RTK_ROM_VERSION_CMD_STATE gchip_type_cmd_state;
+static int gHwFlowControlEnable;
+static int gFinalSpeed;
+
+/* signature: Realtech */
+static const uint8_t RTK_EPATCH_SIGNATURE[8] = {0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x63, 0x68};
+/* Extension Section IGNATURE:0x77FD0451 */
+static const uint8_t Extension_Section_SIGNATURE[4] = {0x51, 0x04, 0xFD, 0x77};
+
+static int serial_fd;
+static int h5_max_retries = 40;
+static struct rtk_h5_struct rtk_h5;
+static struct patch_struct rtk_patch;
+
+/* bite reverse in bytes
+ 00000001 -> 10000000
+ 00000100 -> 00100000
+ */
+static const uint8_t byte_rev_table[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+/* reverse bit */
+static __inline uint8_t bit_rev8(uint8_t byte)
+{
+ return byte_rev_table[byte];
+}
+
+/* reverse bit */
+static __inline uint16_t bit_rev16(uint16_t x)
+{
+ return (bit_rev8(x & 0xff) << 8) | bit_rev8(x >> 8);
+}
+
+static const uint16_t crc_table[] = {
+ 0x0000, 0x1081, 0x2102, 0x3183,
+ 0x4204, 0x5285, 0x6306, 0x7387,
+ 0x8408, 0x9489, 0xa50a, 0xb58b,
+ 0xc60c, 0xd68d, 0xe70e, 0xf78f
+};
+
+/**
+* Malloc the socket buffer
+*
+* @param skb socket buffer
+* @return the point to the malloc buffer
+*/
+static __inline struct sk_buff *skb_alloc(uint32_t len)
+{
+ struct sk_buff *skb = NULL;
+ skb = malloc(len + 8);
+ if (skb) {
+ skb->max_len = len;
+ skb->data_len = 0;
+ memset(skb->data, 0, len);
+ } else {
+ RS_ERR("Allocate skb fails!!!");
+ skb = NULL;
+ }
+ return skb;
+}
+
+/**
+* Free the socket buffer
+*
+* @param skb socket buffer
+*/
+static __inline void skb_free(struct sk_buff *skb)
+{
+ free(skb);
+ return;
+}
+
+/**
+* Increase the date length in sk_buffer by len,
+* and return the increased header pointer
+*
+* @param skb socket buffer
+* @param len length want to increase
+* @return the pointer to increased header
+*/
+static uint8_t *skb_put(struct sk_buff *skb, uint32_t len)
+{
+ uint32_t old_len = skb->data_len;
+ if ((skb->data_len + len) > (skb->max_len)) {
+ RS_ERR("Buffer too small");
+ return NULL;
+ }
+ skb->data_len += len;
+ return (skb->data + old_len);
+}
+
+/**
+* decrease data length in sk_buffer by to len by cut the tail
+*
+* @warning len should be less than skb->len
+*
+* @param skb socket buffer
+* @param len length want to be changed
+*/
+static void skb_trim(struct sk_buff *skb, int len)
+{
+ if (skb->data_len > len) {
+ skb->data_len = len;
+ } else {
+ RS_ERR("Error: skb->data_len(%ld) < len(%d)", (long int)skb->data_len, len);
+ }
+}
+
+/**
+* Decrease the data length in sk_buffer by len,
+* and move the content forward to the header.
+* the data in header will be removed.
+*
+* @param skb socket buffer
+* @param len length of data
+* @return new data
+*/
+static uint8_t *skb_pull(struct sk_buff *skb, uint32_t len)
+{
+ skb->data_len -= len;
+ char *buf;
+ buf = malloc(skb->data_len);
+ if (!buf) {
+ RS_ERR("Unable to allocate file buffer");
+ exit(1);
+ }
+ memcpy(buf, skb->data+len, skb->data_len);
+ memcpy(skb->data, buf, skb->data_len);
+ free(buf);
+ return skb->data;
+}
+
+/**
+* Add "d" into crc scope, caculate the new crc value
+*
+* @param crc crc data
+* @param d one byte data
+*/
+static void h5_crc_update(uint16_t *crc, uint8_t d)
+{
+ uint16_t reg = *crc;
+
+ reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f];
+ reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f];
+
+ *crc = reg;
+}
+
+struct __una_u16 { uint16_t x; };
+
+static __inline uint16_t __get_unaligned_cpu16(const void *p)
+{
+ const struct __una_u16 *ptr = (const struct __una_u16 *)p;
+ return ptr->x;
+}
+
+static __inline uint16_t get_unaligned_be16(const void *p)
+{
+ return __get_unaligned_cpu16((const uint8_t *)p);
+}
+
+/**
+* Get crc data.
+*
+* @param h5 realtek h5 struct
+* @return crc data
+*/
+static uint16_t h5_get_crc(struct rtk_h5_struct *h5)
+{
+ uint16_t crc = 0;
+ uint8_t *data = h5->rx_skb->data + h5->rx_skb->data_len - 2;
+ crc = data[1] + (data[0] << 8);
+ return crc;
+}
+
+/**
+* Just add 0xc0 at the end of skb,
+* we can also use this to add 0xc0 at start while there is no data in skb
+*
+* @param skb socket buffer
+*/
+static void h5_slip_msgdelim(struct sk_buff *skb)
+{
+ const char pkt_delim = 0xc0;
+ memcpy(skb_put(skb, 1), &pkt_delim, 1);
+}
+
+/**
+* Slip ecode one byte in h5 proto, as follows:
+* 0xc0 -> 0xdb, 0xdc
+* 0xdb -> 0xdb, 0xdd
+* 0x11 -> 0xdb, 0xde
+* 0x13 -> 0xdb, 0xdf
+* others will not change
+*
+* @param skb socket buffer
+* @c pure data in the one byte
+*/
+static void h5_slip_one_byte(struct sk_buff *skb, uint8_t c)
+{
+ const int8_t esc_c0[2] = { 0xdb, 0xdc };
+ const int8_t esc_db[2] = { 0xdb, 0xdd };
+ const int8_t esc_11[2] = { 0xdb, 0xde };
+ const int8_t esc_13[2] = { 0xdb, 0xdf };
+
+ switch (c) {
+ case 0xc0:
+ memcpy(skb_put(skb, 2), &esc_c0, 2);
+ break;
+ case 0xdb:
+ memcpy(skb_put(skb, 2), &esc_db, 2);
+ break;
+ case 0x11:
+ memcpy(skb_put(skb, 2), &esc_11, 2);
+ break;
+ case 0x13:
+ memcpy(skb_put(skb, 2), &esc_13, 2);
+ break;
+ default:
+ memcpy(skb_put(skb, 1), &c, 1);
+ }
+}
+
+/**
+* Decode one byte in h5 proto, as follows:
+* 0xdb, 0xdc -> 0xc0
+* 0xdb, 0xdd -> 0xdb
+* 0xdb, 0xde -> 0x11
+* 0xdb, 0xdf -> 0x13
+* others will not change
+*
+* @param h5 realtek h5 struct
+* @byte pure data in the one byte
+*/
+static void h5_unslip_one_byte(struct rtk_h5_struct *h5, char byte)
+{
+ const uint8_t c0 = 0xc0, db = 0xdb;
+ const uint8_t oof1 = 0x11, oof2 = 0x13;
+ //RS_DBG("HCI 3wire h5_unslip_one_byte");
+
+ if (H5_ESCSTATE_NOESC == h5->rx_esc_state) {
+ if (0xdb == byte) {
+ h5->rx_esc_state = H5_ESCSTATE_ESC;
+ } else {
+ memcpy(skb_put(h5->rx_skb, 1), &byte, 1);
+ //Check Pkt Header's CRC enable bit
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC) {
+ h5_crc_update(&h5->message_crc, byte);
+ }
+ h5->rx_count--;
+ }
+ } else if (H5_ESCSTATE_ESC == h5->rx_esc_state) {
+ switch (byte) {
+ case 0xdc:
+ memcpy(skb_put(h5->rx_skb, 1), &c0, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, 0xc0);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ case 0xdd:
+ memcpy(skb_put(h5->rx_skb, 1), &db, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, 0xdb);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ case 0xde:
+ memcpy(skb_put(h5->rx_skb, 1), &oof1, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, oof1);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ case 0xdf:
+ memcpy(skb_put(h5->rx_skb, 1), &oof2, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, oof2);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ default:
+ RS_ERR("Error: Invalid byte %02x after esc byte", byte);
+ skb_free(h5->rx_skb);
+ h5->rx_skb = NULL;
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ break;
+ }
+ }
+}
+
+/**
+* Prepare h5 packet, packet format as follow:
+* | LSB 4 octets | 0 ~ 4095 | 2 MSB
+* |packet header | payload | data integrity check |
+*
+* pakcket header fromat is show below:
+* | LSB 3 bits | 3 bits | 1 bits | 1 bits |
+* | 4 bits | 12 bits | 8 bits MSB
+* |sequence number | acknowledgement number | data integrity check present | reliable packet |
+* |packet type | payload length | header checksum
+*
+* @param h5 realtek h5 struct
+* @param data pure data
+* @param len the length of data
+* @param pkt_type packet type
+* @return socket buff after prepare in h5 proto
+*/
+static struct sk_buff *h5_prepare_pkt(struct rtk_h5_struct *h5, uint8_t *data, int32_t len, int32_t pkt_type)
+{
+ struct sk_buff *nskb;
+ uint8_t hdr[4];
+ uint16_t h5_txmsg_crc = 0xffff;
+ int rel, i;
+
+ switch (pkt_type) {
+ case HCI_ACLDATA_PKT:
+ case HCI_COMMAND_PKT:
+ case HCI_EVENT_PKT:
+ rel = 1; /* reliable */
+ break;
+ case H5_ACK_PKT:
+ case H5_VDRSPEC_PKT:
+ case H5_LINK_CTL_PKT:
+ rel = 0; /* unreliable */
+ break;
+ default:
+ RS_ERR("Unknown packet type");
+ return NULL;
+ }
+
+ /* Max len of packet: (original len +4(h5 hdr) + 2(crc)) * 2
+ * (because bytes 0xc0 and 0xdb are escaped, worst case is
+ * when the packet is all made of 0xc0 and 0xdb :))
+ * + 2 (0xc0 delimiters at start and end). */
+ nskb = skb_alloc((len + 6) * 2 + 2);
+ if (!nskb)
+ return NULL;
+
+ /* Add SLIP start byte: 0xc0 */
+ h5_slip_msgdelim(nskb);
+ /* set AckNumber in SlipHeader */
+ hdr[0] = h5->rxseq_txack << 3;
+ h5->is_txack_req = 0;
+
+ if (rel) {
+ /* set reliable pkt bit and SeqNumber */
+ hdr[0] |= 0x80 + h5->msgq_txseq;
+ ++(h5->msgq_txseq);
+ h5->msgq_txseq = (h5->msgq_txseq) & 0x07;
+ }
+
+ /* set DicPresent bit */
+ if (h5->use_crc)
+ hdr[0] |= 0x40;
+
+ /* set packet type and payload length */
+ hdr[1] = ((len << 4) & 0xff) | pkt_type;
+ hdr[2] = (uint8_t)(len >> 4);
+ /* set checksum */
+ hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
+
+ /* Put h5 header */
+ for (i = 0; i < 4; i++) {
+ h5_slip_one_byte(nskb, hdr[i]);
+
+ if (h5->use_crc)
+ h5_crc_update(&h5_txmsg_crc, hdr[i]);
+ }
+
+ /* Put payload */
+ for (i = 0; i < len; i++) {
+ h5_slip_one_byte(nskb, data[i]);
+
+ if (h5->use_crc)
+ h5_crc_update(&h5_txmsg_crc, data[i]);
+ }
+
+ /* Put CRC */
+ if (h5->use_crc) {
+ h5_txmsg_crc = bit_rev16(h5_txmsg_crc);
+ h5_slip_one_byte(nskb, (uint8_t) ((h5_txmsg_crc >> 8) & 0x00ff));
+ h5_slip_one_byte(nskb, (uint8_t) (h5_txmsg_crc & 0x00ff));
+ }
+
+ /* Add SLIP end byte: 0xc0 */
+ h5_slip_msgdelim(nskb);
+ return nskb;
+}
+
+/**
+* Removed controller acked packet from Host's unacked lists
+*
+* @param h5 realtek h5 struct
+*/
+static void h5_remove_acked_pkt(struct rtk_h5_struct *h5)
+{
+ int pkts_to_be_removed = 0;
+ int seqno = 0;
+ int i = 0;
+
+ seqno = h5->msgq_txseq;
+
+ while (pkts_to_be_removed) {
+ if (h5->rxack == seqno)
+ break;
+
+ pkts_to_be_removed--;
+ seqno = (seqno - 1) & 0x07;
+ }
+
+ if (h5->rxack != seqno) {
+ RS_DBG("Peer acked invalid packet");
+ }
+
+ i = 0;
+ for (i = 0; i < 5; ++i) {
+ if (i >= pkts_to_be_removed)
+ break;
+ i++;
+ }
+
+ if (i != pkts_to_be_removed)
+ RS_DBG("Removed only (%d) out of (%d) pkts", i, pkts_to_be_removed);
+}
+
+/**
+* Realtek send pure ack, send a packet only with an ack
+*
+* @param fd uart file descriptor
+*
+*/
+static void rtk_send_pure_ack_down(int fd)
+{
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, NULL, 0, H5_ACK_PKT);
+ write(fd, nskb->data, nskb->data_len);
+ skb_free(nskb);
+ return;
+}
+
+/**
+* Parse hci event command complete, pull the cmd complete event header
+*
+* @param skb socket buffer
+*
+*/
+static void hci_event_cmd_complete(struct sk_buff *skb)
+{
+ struct hci_ev_cmd_complete *ev = NULL;
+ uint16_t opcode = 0;
+ uint8_t status = 0;
+
+ /* omit length check */
+ /* pull hdr */
+ skb_pull(skb, HCI_EVENT_HDR_SIZE);
+ ev = (struct hci_ev_cmd_complete *)skb->data;
+ opcode = le16_to_cpu(ev->opcode);
+
+ RS_DBG("receive hci command complete event with command: %x", opcode);
+ if (DBG_ON) {
+ RS_DBG("Dump event data with event header (header size %d):", sizeof(struct hci_ev_cmd_complete));
+ RS_DUMP(skb->data, skb->data_len);
+ }
+
+ /* pull command complete event header */
+ skb_pull(skb, sizeof(struct hci_ev_cmd_complete));
+
+ switch (opcode) {
+ case HCI_VENDOR_CHANGE_BDRATE:
+ status = skb->data[0];
+ RS_DBG("Change BD Rate with status:%x", status);
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ rtk_h5.link_estab_state = H5_PATCH;
+ break;
+ case HCI_CMD_READ_BD_ADDR:
+ status = skb->data[0];
+ RS_DBG("Read BD Address with Status:%x", status);
+ if (!status) {
+ RS_DBG("BD Address: %8x%8x", *(int *)&skb->data[1], *(int *)&skb->data[5]);
+ }
+ break;
+ case HCI_VENDOR_READ_LMP_VERISION:
+ ghci_version_cmd_state = event_received;
+ status = skb->data[0];
+ RS_DBG("Read RTK LMP version with Status:%x", status);
+ if (0 == status) {
+ hw_cfg_cb.hci_version = *(uint8_t *)(&skb->data[1]);
+ hw_cfg_cb.hci_revision = *(uint8_t *)(&skb->data[2]);
+ hw_cfg_cb.lmp_subversion = le16_to_cpu(*(uint16_t *)(&skb->data[7]));
+ } else {
+ RS_ERR("READ_RTK_ROM_VERISION return status error!");
+ /* Need to do more */
+ }
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ break;
+ case HCI_VENDOR_READ_CHIP_TYPE:
+ gchip_type_cmd_state = event_received;
+ status = skb->data[0];
+ RS_DBG("Read RTK CHIP TYPE with Status:%x", status);
+ if (0 == status) {
+ hw_cfg_cb.chip_type = *(uint8_t *)(&skb->data[1]);
+ } else {
+ RS_ERR("READ_RTK_CHIP_TYPE return status error!");
+ }
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ break;
+ case HCI_VENDOR_READ_RTK_ROM_VERISION:
+ gRom_version_cmd_state = event_received;
+ status = skb->data[0];
+ RS_DBG("Read RTK rom version with Status:%x", status);
+ if (0 == status)
+ gEVersion = skb->data[1];
+ else if (1 == status)
+ gEVersion = 0;
+ else {
+ gEVersion = 0;
+ RS_ERR("READ_RTK_ROM_VERISION return status error!");
+ /* Need to do more */
+ }
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ break;
+ }
+}
+
+/**
+* Check if it's a hci frame, if it is, complete it with response or parse the cmd complete event
+*
+* @param skb socket buffer
+*
+*/
+static void hci_recv_frame(struct sk_buff *skb)
+{
+ char h5sync[2] = {0x01, 0x7E},
+ h5syncresp[2] = {0x02, 0x7D},
+ h5_sync_resp_pkt[0x8] = {0xc0, 0x00, 0x2F, 0x00, 0xD0, 0x02, 0x7D, 0xc0},
+ h5_conf_resp_pkt_to_Ctrl[0x8] = {0xc0, 0x00, 0x2F, 0x00, 0xD0, 0x04, 0x7B, 0xc0},
+ h5conf[3] = {0x03, 0xFC, 0x10},
+ h5confresp[3] = {0x04, 0x7B, 0x10},
+ cmd_complete_evt_code = 0xe;
+
+ if (rtk_h5.link_estab_state == H5_SYNC) { /* sync */
+ if (!memcmp(skb->data, h5sync, 2)) {
+ RS_DBG("Get Sync Pkt\n");
+ write(serial_fd, &h5_sync_resp_pkt, 0x8);
+ } else if (!memcmp(skb->data, h5syncresp, 2)) {
+ RS_DBG("Get Sync Resp Pkt\n");
+ rtk_h5.link_estab_state = H5_CONFIG;
+ }
+ skb_free(skb);
+ } else if (rtk_h5.link_estab_state == H5_CONFIG) { /* config */
+ if (!memcmp(skb->data, h5sync, 0x2)) {
+ write(serial_fd, &h5_sync_resp_pkt, 0x8);
+ RS_DBG("Get SYNC pkt-active mode\n");
+ } else if (!memcmp(skb->data, h5conf, 0x2)) {
+ write(serial_fd, &h5_conf_resp_pkt_to_Ctrl, 0x8);
+ RS_DBG("Get CONFG pkt-active mode\n");
+ } else if (!memcmp(skb->data, h5confresp, 0x2)) {
+ RS_DBG("Get CONFG resp pkt-active mode\n");
+ rtk_h5.link_estab_state = H5_INIT;//H5_PATCH;
+ //rtk_send_pure_ack_down(serial_fd);
+ } else {
+ RS_DBG("H5_CONFIG receive event\n");
+ rtk_send_pure_ack_down(serial_fd);
+ }
+ skb_free(skb);
+ } else if (rtk_h5.link_estab_state == H5_INIT) {
+ if (skb->data[0] == cmd_complete_evt_code) {
+ hci_event_cmd_complete(skb);
+ }
+
+ rtk_send_pure_ack_down(serial_fd);
+ usleep(10000);
+ rtk_send_pure_ack_down(serial_fd);
+ usleep(10000);
+ rtk_send_pure_ack_down(serial_fd);
+ skb_free(skb);
+ } else if (rtk_h5.link_estab_state == H5_PATCH) { /* patch */
+ rtk_patch.nRxIndex = skb->data[6];
+ if (rtk_patch.nRxIndex & 0x80)
+ rtk_patch.nRxIndex &= ~0x80;
+
+ RS_DBG("rtk_patch.nRxIndex %d\n", rtk_patch.nRxIndex);
+ if (rtk_patch.nRxIndex == rtk_patch.nTotal)
+ rtk_h5.link_estab_state = H5_ACTIVE;
+ skb_free(skb);
+ } else {
+ RS_ERR("receive packets in active state");
+ skb_free(skb);
+ }
+}
+
+/**
+* after rx data is parsed, and we got a rx frame saved in h5->rx_skb,
+* this routinue is called.
+* things todo in this function:
+* 1. check if it's a hci frame, if it is, complete it with response or ack
+* 2. see the ack number, free acked frame in queue
+* 3. reset h5->rx_state, set rx_skb to null.
+*
+* @param h5 realtek h5 struct
+*
+*/
+static void h5_complete_rx_pkt(struct rtk_h5_struct *h5)
+{
+ int pass_up = 1;
+ uint16_t *valuep, value_t;
+ H5_PKT_HEADER *h5_hdr = NULL;
+ /* 1 is offset of uint16_t in H5_PKT_HEADER */
+ valuep = (uint16_t *)(h5->rx_skb->data+1);
+ value_t = le16_to_cpu(*valuep);
+ *valuep = value_t;
+ h5_hdr = (H5_PKT_HEADER *)(h5->rx_skb->data);
+ if (h5_hdr->ReliablePkt) {
+ RS_DBG("Received reliable seqno %u from card", h5->rxseq_txack);
+ h5->rxseq_txack = h5_hdr->SeqNumber + 1;
+ h5->rxseq_txack %= 8;
+ h5->is_txack_req = 1;
+ /* send down an empty ack if needed. */
+ }
+
+ h5->rxack = h5_hdr->AckNumber;
+
+ switch (h5_hdr->PktType) {
+ case HCI_ACLDATA_PKT:
+ case HCI_EVENT_PKT:
+ case HCI_SCODATA_PKT:
+ case HCI_COMMAND_PKT:
+ case H5_LINK_CTL_PKT:
+ pass_up = 1;
+ break;
+ default:
+ pass_up = 0;
+ }
+
+ h5_remove_acked_pkt(h5);
+
+ /* decide if we need to pass up. */
+ if (pass_up) {
+ /* remove h5 header and send packet to hci */
+ skb_pull(h5->rx_skb, sizeof(H5_PKT_HEADER));
+ hci_recv_frame(h5->rx_skb);
+ /* should skb be freed here? */
+ } else {
+ /* free skb buffer */
+ skb_free(h5->rx_skb);
+ }
+
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_skb = NULL;
+}
+
+/**
+* Parse the receive data in h5 proto.
+*
+* @param h5 realtek h5 struct
+* @param data point to data received before parse
+* @param count num of data
+* @return reserved count
+*/
+static int h5_recv(struct rtk_h5_struct *h5, void *data, int count)
+{
+ char *ptr;
+ ptr = (char *)data;
+
+ while (count) {
+ if (h5->rx_count) {
+ if (*ptr == 0xc0) {
+ RS_ERR("short h5 packet");
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_START;
+ h5->rx_count = 0;
+ } else {
+ h5_unslip_one_byte(h5, *ptr);
+ }
+ ptr++;
+ count--;
+ continue;
+ }
+
+ switch (h5->rx_state) {
+ case H5_W4_HDR:
+ /* check header checksum. see Core Spec V4 "3-wire uart" page 67 */
+ if ((0xff & (uint8_t) ~(h5->rx_skb->data[0] + h5->rx_skb->data[1] +
+ h5->rx_skb->data[2])) != h5->rx_skb->data[3]) {
+ RS_ERR("h5 hdr checksum error!!!");
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ continue;
+ }
+
+ if (h5->rx_skb->data[0] & 0x80 /* reliable pkt */
+ && (h5->rx_skb->data[0] & 0x07) != h5->rxseq_txack) {
+ RS_ERR("Out-of-order packet arrived, got(%d)expected(%u)",
+ h5->rx_skb->data[0] & 0x07, h5->rxseq_txack);
+ h5->is_txack_req = 1;
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+
+ if (rtk_patch.nTxIndex == rtk_patch.nTotal) {
+ /* depend on weather remote will reset ack numb or not!!!!!!!!!!!!!!!special */
+ rtk_h5.rxseq_txack = h5->rx_skb->data[0] & 0x07;
+ }
+ continue;
+ }
+
+ h5->rx_state = H5_W4_DATA;
+
+ /* payload length: May be 0 */
+ h5->rx_count = (h5->rx_skb->data[1] >> 4) + (h5->rx_skb->data[2] << 4);
+ continue;
+ case H5_W4_DATA:
+ if (h5->rx_skb->data[0] & 0x40) { /* pkt with crc */
+ h5->rx_state = H5_W4_CRC;
+ h5->rx_count = 2;
+ } else {
+ h5_complete_rx_pkt(h5); /* Send ACK */
+ }
+ continue;
+
+ case H5_W4_CRC:
+ if (bit_rev16(h5->message_crc) != h5_get_crc(h5)) {
+ RS_ERR("Checksum failed, computed(%04x)received(%04x)",
+ bit_rev16(h5->message_crc), h5_get_crc(h5));
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ continue;
+ }
+ skb_trim(h5->rx_skb, h5->rx_skb->data_len - 2);
+ h5_complete_rx_pkt(h5);
+ continue;
+
+ case H5_W4_PKT_DELIMITER:
+ switch (*ptr) {
+ case 0xc0:
+ h5->rx_state = H5_W4_PKT_START;
+ break;
+ default:
+ break;
+ }
+ ptr++;
+ count--;
+ break;
+
+ case H5_W4_PKT_START:
+ switch (*ptr) {
+ case 0xc0:
+ ptr++;
+ count--;
+ break;
+ default:
+ h5->rx_state = H5_W4_HDR;
+ h5->rx_count = 4;
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->message_crc = 0xffff;
+
+ /* Do not increment ptr or decrement count
+ * Allocate packet. Max len of a H5 pkt=
+ * 0xFFF (payload) +4 (header) +2 (crc) */
+ h5->rx_skb = skb_alloc(0x1005);
+ if (!h5->rx_skb) {
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ return 0;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return count;
+}
+
+/**
+* Read data to buf from uart.
+*
+* @param fd uart file descriptor
+* @param buf point to the addr where read data stored
+* @param count num of data want to read
+* @return num of data successfully read
+*/
+static int read_check(int fd, void *buf, int count)
+{
+ int res;
+ do {
+ res = read(fd, buf, count);
+ if (res != -1) {
+ buf = (uint8_t *)buf + res;
+ count -= res;
+ return res;
+ }
+ } while (count && (errno == 0 || errno == EINTR));
+ return res;
+}
+
+/**
+* Retry to sync when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 1s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tshy_sig_alarm(int sig)
+{
+ uint8_t h5sync[2] = {0x01, 0x7E};
+ static int retries;
+ struct itimerval value;
+
+ if (retries < h5_max_retries) {
+ retries++;
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, h5sync, sizeof(h5sync), H5_LINK_CTL_PKT);
+ int len = write(serial_fd, nskb->data, nskb->data_len);
+ RS_DBG("3-wire sync pattern resend : %d, len: %d\n", retries, len);
+ skb_free(nskb);
+
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 250000;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 250000;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("H5 sync timed out\n");
+ exit(1);
+}
+
+/**
+* Retry to config when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 1s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tconf_sig_alarm(int sig)
+{
+ uint8_t h5conf[3] = {0x03, 0xFC, 0x14};
+ static int retries;
+ struct itimerval value;
+
+ if (retries < h5_max_retries) {
+ retries++;
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, h5conf, 3, H5_LINK_CTL_PKT);
+ int len = write(serial_fd, nskb->data, nskb->data_len);
+ RS_DBG("3-wire config pattern resend : %d , len: %d", retries, len);
+ skb_free(nskb);
+
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 250000;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 250000;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("H5 config timed out\n");
+ exit(1);
+}
+
+/**
+* Retry to init when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 1s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tinit_sig_alarm(int sig)
+{
+ static int retries;
+ if (retries < h5_max_retries) {
+ retries++;
+ if (rtk_h5.host_last_cmd) {
+ int len = write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire change baudrate re send:%d, len:%d", retries, len);
+ alarm(1);
+ return;
+ } else {
+ RS_DBG("3-wire init timeout without last command stored\n");
+ }
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("H5 init process timed out");
+ exit(1);
+}
+
+/**
+* Retry to download patch when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 3s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tpatch_sig_alarm(int sig)
+{
+ static int retries;
+ if (retries < h5_max_retries) {
+ RS_DBG("patch timerout, retry:\n");
+ if (rtk_h5.host_last_cmd) {
+ write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire download patch re send:%d", retries);
+ }
+ retries++;
+ alarm(3);
+ return;
+ }
+ RS_ERR("H5 patch timed out\n");
+ exit(1);
+}
+
+/**
+* Download patch using hci. For h5 proto, not recv reply for 2s will timeout.
+* Call h5_tpatch_sig_alarm for retry.
+*
+* @param dd uart file descriptor
+* @param index current index
+* @param data point to the config file
+* @param len current buf length
+* @return #0 on success
+*
+*/
+static int hci_download_patch(int dd, int index, uint8_t *data, int len, struct termios *ti)
+{
+ uint8_t hcipatch[256] = {0x20, 0xfc, 00};
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+
+ sa.sa_handler = h5_tpatch_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+ alarm(2);
+
+ download_vendor_patch_cp cp;
+ memset(&cp, 0, sizeof(cp));
+ cp.index = index;
+ if (data != NULL) {
+ memcpy(cp.data, data, len);
+ }
+
+ int nValue = rtk_patch.nTotal|0x80;
+ if (index == nValue) {
+ rtk_patch.nTxIndex = rtk_patch.nTotal;
+ } else {
+ rtk_patch.nTxIndex = index;
+ }
+ hcipatch[2] = len+1;
+ memcpy(hcipatch+3, &cp, len+1);
+
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, hcipatch, len+4, HCI_COMMAND_PKT); /* data: len + head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ len = write(dd, nskb->data, nskb->data_len);
+ RS_DBG("hci_download_patch nTxIndex:%d nRxIndex: %d\n", rtk_patch.nTxIndex, rtk_patch.nRxIndex);
+
+ if (index & 0x80) {
+ RS_DBG("Hw Flow Control enable after last command sent before last event recv ! ");
+ if (tcsetattr(dd, TCSADRAIN, ti) < 0) {
+ RS_ERR("Can't set port settings");
+ return -1;
+ }
+ }
+
+ while (rtk_patch.nRxIndex != rtk_patch.nTxIndex) { /* receive data and wait last pkt */
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return -1;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+
+ alarm(0);
+ return 0;
+}
+
+/**
+* Download h4 patch
+*
+* @param dd uart file descriptor
+* @param index current index
+* @param data point to the config file
+* @param len current buf length
+* @return ret_index
+*
+*/
+static int hci_download_patch_h4(int dd, int index, uint8_t *data, int len)
+{
+ char bytes[257] = {0};
+ char buf[257] = {0x01, 0x20, 0xfc, 00};
+
+ RS_DBG("dd:%d, index:%d, len:%d", dd, index, len);
+ if (NULL != data) {
+ memcpy(&buf[5], data, len);
+ }
+
+ int cur_index = index;
+ int ret_Index = -1;
+
+ /* Set data struct. */
+ buf[3] = len + 1; /* add index */
+ buf[4] = cur_index;
+ size_t total_len = len + 5;
+
+ /* write */
+ uint16_t w_len;
+ w_len = write(dd, buf, total_len);
+ RS_DBG("h4 write success with len: %d.\n", w_len);
+
+ uint16_t res;
+ res = read(dd, bytes, 8);
+
+ if (DBG_ON) {
+ RS_DBG("h4 read success with len: %d.\n", res);
+ int i = 0;
+ for (i = 0; i < 8; i++) {
+ fprintf(stderr, "byte[%d] = 0x%x\n", i, bytes[i]);
+ }
+ }
+
+ uint8_t rstatus;
+ if ((0x04 == bytes[0]) && (0x20 == bytes[4]) && (0xfc == bytes[5])) {
+ ret_Index = bytes[7];
+ rstatus = bytes[6];
+ RS_DBG("---->ret_Index:%d, ----->rstatus:%d\n", ret_Index, rstatus);
+ if (0x00 != rstatus) {
+ RS_ERR("---->read event status is wrong.\n");
+ return -1;
+ }
+ } else {
+ RS_ERR("==========>Didn't read curret data.\n");
+ return -1;
+ }
+
+ return ret_Index;
+}
+
+/**
+* Realtek change speed with h4 proto. Using vendor specified command packet to achieve this.
+*
+* @warning before write, need to wait 1s for device up
+*
+* @param fd uart file descriptor
+* @param baudrate the speed want to change
+* @return #0 on success
+*/
+static int rtk_vendor_change_speed_h4(int fd, uint32_t baudrate)
+{
+ char bytes[257];
+ uint8_t cmd[8] = {0};
+
+ cmd[0] = 1; /* cmd */
+ cmd[1] = 0x17; /* ocf */
+ cmd[2] = 0xfc; /* ogf, vendor specified */
+
+ cmd[3] = 4; /* length */
+#ifdef BAUDRATE_4BYTES
+ memcpy((uint16_t *)&cmd[4], &baudrate, 4);
+#else
+ memcpy((uint16_t *)&cmd[4], &baudrate, 2);
+
+ cmd[6] = 0;
+ cmd[7] = 0;
+#endif
+
+ /* wait for a while for device to up, just h4 need it */
+ sleep(1);
+
+ if (write(fd, cmd, 8) != 8) {
+ RS_ERR("H4 change uart speed error when writing vendor command");
+ return -1;
+ }
+ RS_DBG("H4 Change uart Baudrate after write ");
+ int res;
+ res = read(fd, bytes, sizeof(bytes));
+
+ if (DBG_ON) {
+ RS_DBG("Realtek Receving H4 change uart speed event:%x", res);
+ RS_DUMP(bytes, res);
+ }
+ if ((0x04 == bytes[0]) && (0x17 == bytes[4]) && (0xfc == bytes[5])) {
+ RS_DBG("H4 change uart speed success, receving status:%x", bytes[6]);
+ if (bytes[6] == 0)
+ return 0;
+ }
+ return -1;
+}
+
+/**
+* Parse realtek Bluetooth config file.
+* The config file if begin with vendor magic: RTK_VENDOR_CONFIG_MAGIC(8723ab55)
+* bt_addr is followed by 0x3c offset, it will be changed by bt_addr param
+* proto, baudrate and flow control is followed by 0xc offset,
+*
+* @param config_buf point to config file content
+* @param filelen length of config file
+* @param bt_addr where bt addr is stored
+* @return baudrate in config file
+*
+*/
+
+static uint32_t rtk_parse_config_file(uint8_t *config_buf, size_t filelen, char bt_addr[6])
+{
+ struct rtk_bt_vendor_config *config = (struct rtk_bt_vendor_config *) config_buf;
+ uint16_t config_len = le16_to_cpu(config->data_len), temp = 0;
+ struct rtk_bt_vendor_config_entry *entry = config->entry;
+
+ uint16_t i;
+ uint32_t baudrate = 0;
+
+ if (le32_to_cpu(config->signature) != RTK_VENDOR_CONFIG_MAGIC) {
+ RS_ERR("config signature magic number(%x) is not set to RTK_VENDOR_CONFIG_MAGIC", (int)config->signature);
+ return 0;
+ }
+
+ if (config_len != filelen - sizeof(struct rtk_bt_vendor_config)) {
+ RS_ERR("config len(%x) is not right(%x)", config_len, filelen-sizeof(struct rtk_bt_vendor_config));
+ return 0;
+ }
+
+ for (i = 0; i < config_len;) {
+ switch (le16_to_cpu(entry->offset)) {
+ case 0x3c:
+ {
+ int j = 0;
+ for (j = 0; j < entry->entry_len; j++)
+ entry->entry_data[j] = bt_addr[entry->entry_len - 1 - j];
+ }
+ break;
+ case 0xc:
+#ifdef BAUDRATE_4BYTES
+ baudrate = *(uint32_t *)entry->entry_data;
+#else
+ baudrate = *(uint16_t *)entry->entry_data;
+#endif
+ gHwFlowControlEnable = 0;
+ if (entry->entry_len >= 12) { //0ffset 0x18 - 0xc
+ gHwFlowControlEnable = (entry->entry_data[12] & 0x4) ? 1:0; //0x18 byte bit2
+ }
+ RS_DBG("config baud rate to :%x, hwflowcontrol:%x, %x", (int)baudrate, entry->entry_data[12], gHwFlowControlEnable);
+ break;
+ default:
+ RS_DBG("config offset(%x),length(%x)", entry->offset, entry->entry_len);
+ break;
+ }
+ temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+ i += temp;
+ entry = (struct rtk_bt_vendor_config_entry *)((uint8_t *)entry + temp);
+ }
+
+ return baudrate;
+}
+
+/**
+* get random realtek Bluetooth addr.
+*
+* @param bt_addr where bt addr is stored
+*
+*/
+static void rtk_get_ram_addr(char bt_addr[0])
+{
+ srand(time(NULL)+getpid()+getpid()*987654+rand());
+
+ uint32_t addr = rand();
+ memcpy(bt_addr, &addr, sizeof(uint8_t));
+}
+
+/**
+* Write the random bt addr to the file /data/misc/bluetooth/btmac.txt.
+*
+* @param bt_addr where bt addr is stored
+*
+*/
+static void rtk_write_btmac2file(char bt_addr[6])
+{
+ int fd;
+ mkdir(BT_ADDR_DIR, 0777);
+ fd = open(BT_ADDR_FILE, O_CREAT|O_RDWR|O_TRUNC, 0666);
+
+ if (fd > 0) {
+ chmod(BT_ADDR_FILE, 0666);
+ char addr[18] = {0};
+ addr[17] = '\0';
+ sprintf(addr, "%2x:%2x:%2x:%2x:%2x:%2x", bt_addr[0], bt_addr[1], bt_addr[2], bt_addr[3], bt_addr[4], bt_addr[5]);
+ write(fd, addr, strlen(addr));
+ close(fd);
+ } else {
+ RS_ERR("open file error:%s\n", BT_ADDR_FILE);
+ }
+}
+
+/**
+* Get realtek Bluetooth config file. The bt addr arg is stored in /data/btmac.txt, if there is not this file,
+* change to /data/misc/bluetooth/btmac.txt. If both of them are not found, using
+* random bt addr.
+*
+* The config file is rtk8723_bt_config whose bt addr will be changed by the one read previous
+*
+* @param config_buf point to the content of realtek Bluetooth config file
+* @param config_baud_rate the baudrate set in the config file
+* @return file_len the length of config file
+*/
+static int rtk_get_bt_config(uint8_t **config_buf, uint32_t *config_baud_rate, patch_info *info)
+{
+ char bt_config_file_name[PATH_MAX] = {0};
+ char bt_addr[6] = {0x00, 0xe0, 0x4c, 0x88, 0x88, 0x88};
+ struct stat st;
+ size_t filelen;
+ int fd;
+ FILE *file = NULL;
+ int i = 0;
+
+ sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, "btmac.txt");
+ RS_DBG("BT mac addr file: %s", bt_config_file_name);
+ if (stat(bt_config_file_name, &st) < 0) {
+ RS_ERR("can't access bt bt_mac_addr file:%s, try use another path", bt_config_file_name);
+ sprintf(bt_config_file_name, BT_ADDR_FILE);
+ if (stat(bt_config_file_name, &st) < 0) {
+ RS_ERR("can't access bt bt_mac_addr file:%s, try use ramdom BT Addr", bt_config_file_name);
+
+ for (i = 0; i < 6; i++)
+ rtk_get_ram_addr(&bt_addr[i]);
+ rtk_write_btmac2file(bt_addr);
+ goto GET_CONFIG;
+ }
+ }
+
+ filelen = st.st_size;
+ file = fopen(bt_config_file_name, "rb");
+ if (file == NULL) {
+ RS_ERR("Can't open bt btaddr file, just use preset BT Addr");
+ } else {
+ fscanf(file, "%2x:%2x:%2x:%2x:%2x:%2x", (int *)&bt_addr[0], (uint32_t *)&bt_addr[1], (uint32_t *)&bt_addr[2], (uint32_t *)&bt_addr[3], (uint32_t *)&bt_addr[4], (uint32_t *)&bt_addr[5]);
+ /* do not set bt_add[0] to zero */
+ /* reserve LAP addr from 0x9e8b00 to 0x9e8b3f, change to 0x008b */
+ if (0x9e == bt_addr[3] && 0x8b == bt_addr[4] && (bt_addr[5] <= 0x3f)) {
+ /* get random value */
+ bt_addr[3] = 0x00;
+ }
+ RS_DBG("BT MAC IS : %02X:%02X:%02X:%02X:%02X:%02X", bt_addr[0], bt_addr[1], bt_addr[2], bt_addr[3], bt_addr[4], bt_addr[5]);
+ }
+
+GET_CONFIG:
+ if (info != NULL) {
+ sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, info->config_name);
+ } else {
+ sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, "rtlbt_config");
+ }
+ RS_DBG("Final bt config file: %s", bt_config_file_name);
+
+ if (stat(bt_config_file_name, &st) < 0) {
+ RS_ERR("Can't access firmware, errno:%d", errno);
+ return -1;
+ }
+
+ filelen = st.st_size;
+
+ fd = open(bt_config_file_name, O_RDONLY);
+ if (fd < 0) {
+ perror("Can't open bt config file");
+ return -1;
+ }
+
+ *config_buf = malloc(filelen);
+ if (*config_buf == NULL) {
+ RS_DBG("malloc buffer for config file fail(%x)\n", filelen);
+ close(fd);
+ return -1;
+ }
+
+ /* we may need to parse this config file. */
+ /* for easy debug, only get need data. */
+ if (read(fd, *config_buf, filelen) < (ssize_t)filelen) {
+ perror("Can't load bt config file");
+ free(*config_buf);
+ *config_buf = NULL;
+ close(fd);
+ return -1;
+ }
+
+ *config_baud_rate = rtk_parse_config_file(*config_buf, filelen, bt_addr);
+ RS_DBG("Get config baud rate(4 bytes) from config file:%x", (int)*config_baud_rate);
+
+ close(fd);
+ return filelen;
+}
+
+/**
+* Realtek change speed with h5 proto. Using vendor specified command packet to achieve this.
+*
+* @warning it will waiting 2s for reply.
+*
+* @param fd uart file descriptor
+* @param baudrate the speed want to change
+*
+*/
+static int rtk_vendor_change_speed_h5(int fd, uint32_t baudrate)
+{
+ struct sk_buff *cmd_change_bdrate = NULL;
+ uint8_t cmd[7] = {0};
+ int retlen;
+ char bytes[READ_DATA_SIZE];
+ struct sigaction sa;
+
+ sa.sa_handler = h5_tinit_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ cmd[0] = 0x17; /* ocf */
+ cmd[1] = 0xfc; /* ogf, vendor specified */
+
+ cmd[2] = 4; /* length */
+#ifdef BAUDRATE_4BYTES
+ memcpy((uint16_t *)&cmd[3], &baudrate, 4);
+#else
+ memcpy((uint16_t *)&cmd[3], &baudrate, 2);
+ cmd[5] = 0;
+ cmd[6] = 0;
+#endif
+
+ if (DBG_ON) {
+ RS_DUMP(cmd, 7);
+ RS_DBG("change speed command ready baudrate=%d n", baudrate);
+ }
+ cmd_change_bdrate = h5_prepare_pkt(&rtk_h5, cmd, 7, HCI_COMMAND_PKT);
+ if (!cmd_change_bdrate) {
+ RS_ERR("Prepare command packet for change speed fail");
+ return -1;
+ }
+
+ rtk_h5.host_last_cmd = cmd_change_bdrate;
+ alarm(1);
+ write(fd, cmd_change_bdrate->data, cmd_change_bdrate->data_len);
+
+ while (rtk_h5.link_estab_state == H5_INIT) {
+ retlen = read_check(fd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return -1;
+ }
+
+ /* add pure ack check */
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+
+ alarm(0);
+ return 0;
+}
+
+/**
+* Init realtek Bluetooth h5 proto. h5 proto is added by realtek in the right kernel.
+* Generally there are two steps: h5 sync and h5 config
+*
+* @param fd uart file descriptor
+* @param ti termios struct
+*
+*/
+static int rtk_init_h5(int fd, struct termios *ti)
+{
+ char bytes[READ_DATA_SIZE];
+ struct sigaction sa;
+ int retlen;
+ struct itimerval value;
+
+ /* set even parity here */
+ ti->c_cflag |= PARENB;
+ ti->c_cflag &= ~(PARODD);
+ if (tcsetattr(fd, TCSANOW, ti) < 0) {
+ RS_ERR("Can't set port settings");
+ return -1;
+ }
+
+ alarm(0);
+ serial_fd = fd;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = h5_tshy_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ /* h5 sync */
+ h5_tshy_sig_alarm(0);
+ memset(&rtk_h5, 0, sizeof(rtk_h5));
+ rtk_h5.link_estab_state = H5_SYNC;
+ while (rtk_h5.link_estab_state == H5_SYNC) {
+ retlen = read_check(fd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ RS_ERR("H5 Read Sync Response Failed");
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+ return -1;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ /* h5 config */
+ sa.sa_handler = h5_tconf_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+ h5_tconf_sig_alarm(0);
+ while (rtk_h5.link_estab_state == H5_CONFIG) {
+ retlen = read_check(fd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ RS_ERR("H5 Read Config Response Failed");
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+ return -1;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ rtk_send_pure_ack_down(fd);
+ RS_DBG("H5 init finished\n");
+ return 0;
+}
+
+/**
+* Download realtek firmware and config file from uart with the proto.
+* Parse the content to serval packets follow the proto and then write the packets from uart
+*
+* @param fd uart file descriptor
+* @param buf addr where stor the content of firmware and config file
+* @param filesize length of buf
+* @param is_sent_changerate if baudrate need to be changed
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+*
+*/
+static void rtk_download_fw_config(int fd, uint8_t *buf, size_t filesize, int is_sent_changerate, int proto, struct termios *ti)
+{
+ uint8_t iCurIndex = 0;
+ uint8_t iCurLen = 0;
+ uint8_t iEndIndex = 0;
+ uint8_t iLastPacketLen = 0;
+ uint8_t iAdditionPkt = 0;
+ uint8_t iTotalIndex = 0;
+ uint8_t iCmdSentNum = 0; /* the number of CMDs which have been sent */
+ uint8_t *bufpatch;
+
+ iEndIndex = (uint8_t)((filesize-1)/PATCH_DATA_FIELD_MAX_SIZE);
+ iLastPacketLen = (filesize)%PATCH_DATA_FIELD_MAX_SIZE;
+
+ if (is_sent_changerate)
+ iCmdSentNum++;
+ if (gRom_version_cmd_state >= cmd_has_sent)
+ iCmdSentNum++;
+ if (ghci_version_cmd_state >= cmd_has_sent)
+ iCmdSentNum++;
+ if (gchip_type_cmd_state >= cmd_has_sent)
+ iCmdSentNum++;
+
+ iAdditionPkt = (iEndIndex+1+iCmdSentNum)%8?(8-(iEndIndex+1+iCmdSentNum)%8):0;
+ iTotalIndex = iAdditionPkt + iEndIndex;
+ rtk_patch.nTotal = iTotalIndex; /* init TotalIndex */
+
+ RS_DBG("iEndIndex:%d iLastPacketLen:%d iAdditionpkt:%d\n", iEndIndex, iLastPacketLen, iAdditionPkt);
+
+ if (iLastPacketLen == 0)
+ iLastPacketLen = PATCH_DATA_FIELD_MAX_SIZE;
+
+ bufpatch = buf;
+
+ int i;
+ for (i = 0; i <= iTotalIndex; i++) {
+ if (iCurIndex < iEndIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = PATCH_DATA_FIELD_MAX_SIZE;
+ } else if (iCurIndex == iEndIndex) { /* send last data packet */
+ if (iCurIndex == iTotalIndex)
+ iCurIndex = iCurIndex | 0x80;
+ else
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = iLastPacketLen;
+ } else if (iCurIndex < iTotalIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ bufpatch = NULL;
+ iCurLen = 0;
+ } else { /* send end packet */
+ bufpatch = NULL;
+ iCurLen = 0;
+ iCurIndex = iCurIndex|0x80;
+ }
+
+ if (iCurIndex & 0x80)
+ RS_DBG("Send FW last command");
+
+ if (proto == HCI_UART_H4) {
+ iCurIndex = hci_download_patch_h4(fd, iCurIndex, bufpatch, iCurLen);
+ if ((iCurIndex != i) && (i != rtk_patch.nTotal)) {
+ /* check index but ignore last pkt */
+ RS_DBG("index mismatch i:%d iCurIndex:%d, patch fail\n", i, iCurIndex);
+ return;
+ }
+ } else if (proto == HCI_UART_3WIRE)
+ hci_download_patch(fd, iCurIndex, bufpatch, iCurLen, ti);
+
+ if (iCurIndex < iEndIndex) {
+ bufpatch += PATCH_DATA_FIELD_MAX_SIZE;
+ }
+ iCurIndex++;
+ }
+
+ /* set last ack packet down */
+ if (proto == HCI_UART_3WIRE) {
+ rtk_send_pure_ack_down(fd);
+ }
+}
+
+/**
+* Get realtek Bluetooth firmaware file. The content will be saved in *fw_buf which is malloc here.
+* The length malloc here will be lager than length of firmware file if there is a config file.
+* The content of config file will copy to the tail of *fw_buf in rtk_config.
+*
+* @param fw_buf point to the addr where stored the content of firmware.
+* @param addi_len length of config file.
+* @return length of *fw_buf.
+*
+*/
+static int rtk_get_bt_firmware(uint8_t **fw_buf, size_t addi_len, patch_info *info)
+{
+ char filename[PATH_MAX] = {0};
+ struct stat st;
+ int fd = -1;
+ size_t fwsize, buf_size;
+
+ if (info != NULL) {
+ sprintf(filename, "%s/%s", FIRMWARE_DIRECTORY, info->patch_name);
+ } else {
+ sprintf(filename, "%s/%s", FIRMWARE_DIRECTORY, "rtlbt_fw");
+ }
+
+ RS_DBG("Final bt firmware file: %s", filename);
+
+ if (stat(filename, &st) < 0) {
+ RS_ERR("Can't access firmware, errno:%d", errno);
+ return -1;
+ }
+
+ fwsize = st.st_size;
+ buf_size = fwsize + addi_len;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ RS_ERR("Can't open firmware, errno:%d", errno);
+ return -1;
+ }
+
+ *fw_buf = malloc(buf_size);
+ if (!(*fw_buf)) {
+ RS_ERR("Can't alloc memory for fw&config, errno:%d", errno);
+ close(fd);
+ return -1;
+ }
+
+ if (read(fd, *fw_buf, fwsize) < (ssize_t) fwsize) {
+ free(*fw_buf);
+ *fw_buf = NULL;
+ close(fd);
+ return -1;
+ }
+ RS_DBG("Load FW OK");
+ close(fd);
+ return buf_size;
+}
+
+/* These two function(rtk<-->uart speed transfer) need check Host uart speed at first!!!! IMPORTANT
+ * add more speed if neccessary */
+typedef struct _baudrate_ex {
+ uint32_t rtk_speed;
+ int uart_speed;
+} baudrate_ex;
+
+#ifdef BAUDRATE_4BYTES
+static baudrate_ex baudrates[] = {
+ {0x00006004, 921600},
+ {0x05F75004, 921600}, // RTL8723BS
+ {0x00004003, 1500000},
+ {0x04928002, 1500000}, // RTL8723BS
+ {0x00005002, 2000000}, // same as RTL8723AS
+ {0x00008001, 3000000},
+ {0x00009001, 3000000}, // Lory add new, t169 and t9e use 0x00009001.
+ {0x06DD8001, 3000000}, // RTL8723BS, Baudrate: 2920000
+ {0x036D8001, 3000000}, // RTL8723BS, Baudrate: 2929999
+ {0x06B58001, 3000000}, // RTL8723BS, Baudrate: 2940000
+ {0x02B58001, 3000000}, // RTL8723BS, Baudrate: 2945000
+ {0x02D58001, 3000000}, // RTL8723BS, Baudrate: 2950000
+ {0x05558001, 3000000}, // RTL8723BS, Baudrate: 2960000
+ {0x02AA8001, 3000000}, // RTL8723BS, Baudrate: 2969999
+ {0x052A8001, 3000000}, // RTL8723BS, Baudrate: 2980000
+ {0x04928001, 3000000}, // RTL8723BS, Baudrate: 2998000
+ {0x00007001, 3500000},
+ {0x052A6001, 3500000}, // RTL8723BS
+ {0x00005001, 4000000}, // same as RTL8723AS
+ {0x05AD9005, 547000},
+ {0x0252C00A, 230400},
+ {0x0000701d, 115200},
+ {0x0252C002, 115200}, // RTL8723BS
+ {0x0252C014, 115200} // RTL8723BS
+};
+
+#else
+static baudrate_ex baudrates[] = {
+ {0x7001, 3500000},
+ {0x6004, 921600},
+ {0x4003, 1500000},
+ {0x5001, 4000000},
+ {0x5002, 2000000},
+ {0x8001, 3000000},
+ {0x9001, 3000000},
+ {0x701d, 115200}
+};
+
+#endif
+
+
+/**
+* Change realtek Bluetooth speed to uart speed. It is matching in the struct baudrates:
+*
+* @code
+* baudrate_ex baudrates[] =
+* {
+* {0x7001, 3500000},
+* {0x6004, 921600},
+* {0x4003, 1500000},
+* {0x5001, 4000000},
+* {0x5002, 2000000},
+* {0x8001, 3000000},
+* {0x701d, 115200}
+* };
+* @endcode
+*
+* If there is no match in baudrates, uart speed will be set as #115200.
+*
+* @param rtk_speed realtek Bluetooth speed
+* @param uart_speed uart speed
+*
+*/
+static void rtk_speed_to_uart_speed(uint32_t rtk_speed, uint32_t *uart_speed)
+{
+ *uart_speed = 115200;
+
+ int i;
+ for (i = 0; i < sizeof(baudrates)/sizeof(baudrate_ex); i++) {
+ if (baudrates[i].rtk_speed == le32_to_cpu(rtk_speed)) {
+ *uart_speed = baudrates[i].uart_speed;
+ return;
+ }
+ }
+ return;
+}
+
+/**
+* Change uart speed to realtek Bluetooth speed. It is matching in the struct baudrates:
+*
+* @code
+* baudrate_ex baudrates[] =
+* {
+* {0x7001, 3500000},
+* {0x6004, 921600},
+* {0x4003, 1500000},
+* {0x5001, 4000000},
+* {0x5002, 2000000},
+* {0x8001, 3000000},
+* {0x701d, 115200}
+* };
+* @endcode
+*
+* If there is no match in baudrates, realtek Bluetooth speed will be set as #0x701D.
+*
+* @param uart_speed uart speed
+* @param rtk_speed realtek Bluetooth speed
+*
+*/
+static inline void uart_speed_to_rtk_speed(int uart_speed, uint32_t *rtk_speed)
+{
+ *rtk_speed = 0x701D;
+
+ int i;
+ for (i = 0; i < sizeof(baudrates) / sizeof(baudrate_ex); i++) {
+ if (baudrates[i].uart_speed == uart_speed) {
+ *rtk_speed = baudrates[i].rtk_speed;
+ return;
+ }
+ }
+
+ return;
+}
+
+static void rtk_get_eversion_timeout(int sig)
+{
+ static int retries;
+ RS_DBG("RTK get HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");
+ if (retries < h5_max_retries) {
+ RS_DBG("patch timerout, retry:\n");
+ if (rtk_h5.host_last_cmd) {
+ write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire download patch re send:%d", retries);
+ }
+ retries++;
+ alarm(3);
+ return;
+ }
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("rtk get eversion cmd complete event timed out\n");
+ exit(1);
+}
+
+/**
+* Send vendor cmd to get eversion: 0xfc6d
+* If Rom code does not support this cmd, use default.
+*/
+static void rtk_get_eversion(int dd)
+{
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+ /* send HCI_VENDOR_READ_RTK_ROM_VERISION Command */
+ uint8_t read_rom_patch_cmd[3] = {0x6d, 0xfc, 0x00};
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 3, HCI_COMMAND_PKT); /* data: len+head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ write(dd, nskb->data, nskb->data_len);
+ gRom_version_cmd_state = cmd_has_sent;
+ RS_DBG("RTK send HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_eversion_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+
+ alarm(3);
+ while (gRom_version_cmd_state != event_received) {
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ alarm(0);
+ return;
+}
+
+static void rtk_get_lmp_version_timeout(int sig)
+{
+ static int retries;
+ RS_DBG("RTK get HCI_VENDOR_READ_RTK_LMP_VERISION_Command\n");
+ if (retries < h5_max_retries) {
+ RS_DBG("patch timerout, retry:\n");
+ if (rtk_h5.host_last_cmd) {
+ write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire download patch re send:%d", retries);
+ }
+ retries++;
+ alarm(3);
+ return;
+ }
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("rtk get lmp version cmd complete event timed out\n");
+ exit(1);
+}
+
+static void rtk_get_lmp_version(int dd)
+{
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+ /* send HCI_VENDOR_READ_RTK_ROM_VERISION_Command */
+ uint8_t read_rom_patch_cmd[3] = {0x01, 0x10, 00};
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 3, HCI_COMMAND_PKT); /* data: len+head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ write(dd, nskb->data, nskb->data_len);
+ ghci_version_cmd_state = cmd_has_sent;
+ RS_DBG("RTK send HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_lmp_version_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+
+ alarm(3);
+ while (ghci_version_cmd_state != event_received) {
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ alarm(0);
+ return;
+}
+
+static void rtk_get_chip_type(int dd)
+{
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+ uint8_t read_rom_patch_cmd[8] = {0x61, 0xfc, 0x05, 0x00, 0x94, 0xa0, 0x00, 0xb0};
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 8, HCI_COMMAND_PKT); /* data: len+head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ write(dd, nskb->data, nskb->data_len);
+ gchip_type_cmd_state = cmd_has_sent;
+ RS_DBG("RTK send HCI_VENDOR_READ_CHIP_TYPE Command");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_lmp_version_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+
+ alarm(3);
+ while (gchip_type_cmd_state != event_received) {
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ alarm(0);
+ return;
+}
+
+static int check_match_state(bt_hw_cfg_cb_t *cfg, uint32_t mask)
+{
+ patch_info *patch_entry;
+ int res = 0;
+
+ for (patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
+ if (patch_entry->lmp_subversion != cfg->lmp_subversion)
+ continue;
+ if ((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL) && ((patch_entry->hci_version_mask & (1 << cfg->hci_version)) == 0))
+ continue;
+ if ((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL) && ((patch_entry->hci_revision_mask & (1 << cfg->hci_revision)) == 0))
+ continue;
+ if ((mask & PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE) && (patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL) && ((patch_entry->chip_type_mask & (1 << cfg->chip_type)) == 0))
+ continue;
+ res++;
+ }
+ RS_DBG("check_match_state return %d(cfg->lmp_subversion:0x%x cfg->hci_vesion:0x%x cfg->hci_revision:0x%x cfg->chip_type:0x%x mask:%08x)",
+ res, cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type, mask);
+ return res;
+}
+
+static patch_info *get_patch_entry(bt_hw_cfg_cb_t *cfg)
+{
+ patch_info *patch_entry;
+
+ RS_DBG("get_patch_entry(lmp_subversion:0x%x hci_vesion:0x%x cfg->hci_revision:0x%x chip_type:0x%x)",
+ cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type);
+ for (patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
+ if (patch_entry->lmp_subversion != cfg->lmp_subversion)
+ continue;
+ if ((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL) && ((patch_entry->hci_version_mask & (1 << cfg->hci_version)) == 0))
+ continue;
+ if ((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL) && ((patch_entry->hci_revision_mask & (1<hci_revision)) == 0))
+ continue;
+ if ((patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL) && ((patch_entry->chip_type_mask & (1<chip_type)) == 0))
+ continue;
+ break;
+ }
+ RS_DBG("get_patch_entry return(patch_name:%s config_name:%s mac_offset:0x%x)",
+ patch_entry->patch_name, patch_entry->config_name, patch_entry->mac_offset);
+ return patch_entry;
+}
+
+/**
+* Config realtek Bluetooth. The configuration parameter is get from config file and fw.
+*
+* @warning maybe only one of config file and fw file exists. The bt_addr arg is stored in "/data/btmac.txt"
+* or "/data/misc/bluetoothd/bt_mac/btmac.txt",
+*
+* @param fd uart file descriptor
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+* @param speed init_speed in uart struct
+* @param ti termios struct
+* @returns #0 on success
+*/
+static int rtk_config(int fd, int proto, int speed, struct termios *ti)
+{
+ int config_len = -1, buf_len = -1, final_speed = 0;
+ uint8_t *config_file_buf = NULL;
+ uint8_t *buf = NULL;
+ uint32_t baudrate = 0;
+
+ uint8_t *epatch_buf = NULL;
+ struct rtk_epatch *epatch_info = NULL;
+ struct rtk_epatch_entry current_entry;
+ uint8_t need_download_fw = 1;
+ patch_info *prtk_patch_file_info = NULL;
+
+ current_entry.start_offset = 0;
+ current_entry.patch_length = 0;
+ current_entry.chipID = 0;
+
+ /*
+ * 1. if both config file and fw exists, use it and change rate according to config file
+ * 2. if config file not exists while fw does, not change baudrate and only download fw
+ * 3. if fw doesnot exist, only change rate to 3.25M or from config file if it exist. This case is only for early debug before any efuse is setting.
+ */
+
+ /* Get version from ROM */
+ rtk_get_lmp_version(fd);
+ if (check_match_state(&hw_cfg_cb, 0) > 1) {
+ rtk_get_chip_type(fd);
+ RS_DBG("lmp_subversion = 0x%x, hci_version = 0x%x, hci_revision = 0x%x, chip_type = 0x%x",
+ hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision, hw_cfg_cb.chip_type);
+ }
+
+ prtk_patch_file_info = get_patch_entry(&hw_cfg_cb);
+
+ if (prtk_patch_file_info == NULL) {
+ RS_ERR("lmp_version is %x, no matched project found!", hw_cfg_cb.lmp_subversion);
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ config_len = rtk_get_bt_config(&config_file_buf, &baudrate, prtk_patch_file_info);
+ if (config_len < 0) {
+ RS_ERR("Get Config file error, just use efuse settings");
+ config_len = 0;
+ }
+
+ buf_len = rtk_get_bt_firmware(&epatch_buf, config_len, prtk_patch_file_info);
+ if (buf_len < 0) {
+ RS_ERR("Get BT firmware error, continue without bt firmware");
+ goto FETCH_DONE;
+ }
+
+ if (hw_cfg_cb.lmp_subversion == ROM_LMP_8723a) {
+ if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) == 0) {
+ RS_ERR("8723as Check signature error!");
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ buf = malloc(buf_len);
+ if (!buf) {
+ RS_ERR("Can't alloc memory for fw&config, errno:%d", errno);
+ buf_len = -1;
+ goto FETCH_DONE;
+ }
+
+ RS_DBG("8723as, fw copy direct");
+ memcpy(buf, epatch_buf, buf_len);
+ } else {
+ /* Get version from ROM */
+ rtk_get_eversion(fd); /* gEVersion is set. */
+ RS_DBG("gEVersion=%d", gEVersion);
+ /* check Extension Section Field */
+ if (memcmp(epatch_buf + buf_len - config_len - 4, Extension_Section_SIGNATURE, 4) != 0) {
+ RS_ERR("Check Extension_Section_SIGNATURE error! do not download fw");
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) != 0) {
+ RS_DBG("Check signature error!");
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ int i = 0;
+ uint32_t value_t = 0;
+ epatch_info = (struct rtk_epatch *)epatch_buf;
+ value_t = le32_to_cpu(epatch_info->fm_version);
+ epatch_info->fm_version = (uint32_t)value_t;
+ value_t = le16_to_cpu(epatch_info->number_of_total_patch);
+ epatch_info->number_of_total_patch = (uint16_t)value_t;
+ RS_DBG("fm_version = 0x%x", epatch_info->fm_version);
+ RS_DBG("number_of_total_patch = %d", epatch_info->number_of_total_patch);
+ /* get right epatch entry */
+ for (i = 0; i < epatch_info->number_of_total_patch; i++) {
+ if (le16_to_cpu(*(uint16_t *)(epatch_buf + 14 + 2 * i)) == gEVersion + 1) {
+ current_entry.chipID = gEVersion + 1;
+ current_entry.patch_length = le16_to_cpu(*(uint16_t *)(epatch_buf + 14 + 2 * epatch_info->number_of_total_patch + 2 * i));
+ current_entry.start_offset = le32_to_cpu(*(uint32_t *)(epatch_buf + 14 + 4 * epatch_info->number_of_total_patch + 4 * i));
+ break;
+ }
+ }
+ RS_DBG("chipID = %d", current_entry.chipID);
+ RS_DBG("patch_length = 0x%x", current_entry.patch_length);
+ RS_DBG("start_offset = 0x%x", current_entry.start_offset);
+ /* get right version patch: buf, buf_len */
+ buf_len = current_entry.patch_length + config_len;
+ RS_DBG("buf_len = 0x%x", buf_len);
+ buf = malloc(buf_len);
+ if (!buf) {
+ RS_ERR("Can't alloc memory for multi fw&config, errno:%d", errno);
+ buf_len = -1;
+ goto FETCH_DONE;
+ }
+ memcpy(buf, &epatch_buf[current_entry.start_offset], current_entry.patch_length);
+ value_t = cpu_to_le32(epatch_info->fm_version);
+ epatch_info->fm_version = (uint32_t)value_t;
+ memcpy(&buf[current_entry.patch_length-4], &epatch_info->fm_version, 4);
+ value_t = cpu_to_le32(epatch_info->fm_version);
+ epatch_info->fm_version = value_t;
+ }
+
+ if (config_len) {
+ memcpy(&buf[buf_len - config_len], config_file_buf, config_len);
+ }
+
+FETCH_DONE:
+ free(epatch_buf);
+ epatch_buf = NULL;
+ if (config_file_buf)
+ free(config_file_buf);
+
+ RS_DBG("Fw:%s exists, config file:%s exists", (buf_len > 0) ? "" : "not", (config_len > 0) ? "" : "not");
+ if ((buf_len > 0) && (config_len == 0)) {
+ rtk_h5.link_estab_state = H5_PATCH;
+ goto DOWNLOAD_FW;
+ }
+
+ /* change baudrate if needed */
+ if (baudrate == 0) {
+ uart_speed_to_rtk_speed(speed, &baudrate);
+ RS_DBG("Since no config file to set uart baudrate, so use user input parameters:%x, %x", (int)speed, (uint32_t)baudrate);
+ } else
+ rtk_speed_to_uart_speed(baudrate, (uint32_t *)&gFinalSpeed);
+
+ if (proto == HCI_UART_3WIRE)
+ rtk_vendor_change_speed_h5(fd, baudrate);
+ else
+ rtk_vendor_change_speed_h4(fd, baudrate);
+
+ usleep(50000);
+ final_speed = gFinalSpeed ? gFinalSpeed : speed;
+ RS_DBG("final_speed %d\n", final_speed);
+ if (set_speed(fd, ti, final_speed) < 0) {
+ RS_ERR("Can't set baud rate:%x, %x, %x", final_speed, gFinalSpeed, speed);
+ return -1;
+ }
+
+ if (gHwFlowControlEnable) {
+ RS_DBG("Hw Flow Control enable");
+ ti->c_cflag |= CRTSCTS;
+ } else {
+ RS_DBG("Hw Flow Control disable");
+ ti->c_cflag &= ~CRTSCTS;
+ }
+ RS_DBG("Hw Flow Control do not enable before download fw! ");
+
+ /* wait for while for controller to setup */
+ usleep(10000);
+
+DOWNLOAD_FW:
+ if (buf && (buf_len > 0) && (need_download_fw)) {
+ /* baudrate 0 means no change baudrate send */
+ memset(&rtk_patch, 0, sizeof(rtk_patch));
+ rtk_patch.nRxIndex = -1;
+
+ rtk_download_fw_config(fd, buf, buf_len, baudrate, proto, ti);
+ free(buf);
+ }
+ RS_DBG("Init Process finished");
+ return 0;
+}
+
+/**
+* Init uart by realtek Bluetooth.
+*
+* @param fd uart file descriptor
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+* @param speed init_speed in uart struct
+* @param ti termios struct
+* @returns #0 on success, depend on rtk_config
+*/
+int rtk_init(int fd, int proto, int speed, struct termios *ti)
+{
+ RS_DBG("Realtek hciattach version %s \n", RTK_VERSION);
+
+ if (proto == HCI_UART_3WIRE) { /*h4 will do nothing for init */
+ rtk_init_h5(fd, ti);
+ }
+ return rtk_config(fd, proto, speed, ti);
+}
+
+/**
+* Post uart by realtek Bluetooth. If gFinalSpeed is set, set uart speed with it.
+*
+* @param fd uart file descriptor
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+* @param ti termios struct
+* @returns #0 on success.
+*/
+int rtk_post(int fd, int proto, struct termios *ti)
+{
+ if (gFinalSpeed) {
+ return set_speed(fd, ti, gFinalSpeed);
+ }
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_sprd.c b/external/cache/sources/hcitools/hciattach_sprd.c
new file mode 100755
index 0000000..612e324
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_sprd.c
@@ -0,0 +1,806 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "hciattach.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+#define LOG_STR "SPRD Bluetooth"
+#define DBG_ON 1
+
+#define SPRD_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n" , LOG_STR, ##arg); \
+ } while(0)
+
+#define SPRD_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror(LOG_STR" ERROR reason"); \
+ } while(0)
+
+#define SPRD_DUMP(buffer, len) \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ do { \
+ int i = 0; \
+ for (i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+#define CONF_ITEM_TABLE(ITEM, ACTION, BUF, LEN) \
+ { #ITEM, ACTION, &(BUF.ITEM), LEN, (sizeof(BUF.ITEM) / LEN) }
+
+#define UINT8_TO_STREAM(p, u8) \
+ { *(p)++ = (uint8_t)(u8); }
+
+#define STREAM_TO_UINT8(u8, p) \
+ { \
+ (u8) = (uint8_t)(*(p)); \
+ (p) += 1; \
+ }
+
+#define UINT16_TO_STREAM(p, u16) \
+ { \
+ *(p)++ = (uint8_t)(u16); \
+ *(p)++ = (uint8_t)((u16) >> 8); \
+ }
+
+#define STREAM_TO_UINT16(u16, p) \
+ { \
+ (u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
+ (p) += 2; \
+ }
+
+#define UINT32_TO_STREAM(p, u32) \
+ { \
+ *(p)++ = (uint8_t)(u32); \
+ *(p)++ = (uint8_t)((u32) >> 8); \
+ *(p)++ = (uint8_t)((u32) >> 16); \
+ *(p)++ = (uint8_t)((u32) >> 24); \
+ }
+
+#define CONF_COMMENT '#'
+#define CONF_DELIMITERS " =\n\r\t"
+#define CONF_VALUES_DELIMITERS "=\n\r\t#"
+#define CONF_VALUES_PARTITION " ,=\n\r\t#"
+#define CONF_MAX_LINE_LEN 255
+
+#define HCI_PSKEY 0xFCA0
+#define HCI_VSC_ENABLE_COMMMAND 0xFCA1
+#define HCI_RF_PARA 0xFCA2
+
+#define RESPONSE_LENGTH 100
+#define HCI_CMD_MAX_LEN 258
+#define HCI_EVT_CMD_CMPL_OPCODE 3
+#define HCI_PACKET_TYPE_COMMAND 1
+#define HCI_CMD_PREAMBLE_SIZE 3
+
+#define FW_NODE_BYTE 6
+#define FW_DATE_D_BYTE 8
+#define FW_DATE_M_BYTE 9
+#define FW_DATE_Y_BYTE 10
+
+#define BT_CONFIG_PATH "/lib/firmware"
+#define BT_HC_HDR_SIZE (sizeof(HC_BT_HDR))
+#define BT_VND_OP_RESULT_SUCCESS 0
+#define BT_VND_OP_RESULT_FAIL 1
+#define MSG_STACK_TO_HC_HCI_CMD 0x2000
+#define START_STOP_CMD_SIZE 3
+#define DUAL_MODE 0
+#define DISABLE_BT 0
+#define ENABLE_BT 1
+
+typedef void (*hci_cback)(void *);
+typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value, void *buf, int len, int size);
+
+typedef struct {
+ uint16_t event;
+ uint16_t len;
+ uint16_t offset;
+ uint16_t layer_specific;
+ uint8_t data[];
+} HC_BT_HDR;
+
+typedef struct {
+ uint32_t device_class;
+ uint8_t feature_set[16];
+ uint8_t device_addr[6];
+ uint16_t comp_id;
+ uint8_t g_sys_uart0_communication_supported;
+ uint8_t cp2_log_mode;
+ uint8_t LogLevel;
+ uint8_t g_central_or_perpheral;
+ uint16_t Log_BitMask;
+ uint8_t super_ssp_enable;
+ uint8_t common_rfu_b3;
+ uint32_t common_rfu_w[2];
+ uint32_t le_rfu_w[2];
+ uint32_t lmp_rfu_w[2];
+ uint32_t lc_rfu_w[2];
+ uint16_t g_wbs_nv_117;
+ uint16_t g_wbs_nv_118;
+ uint16_t g_nbv_nv_117;
+ uint16_t g_nbv_nv_118;
+ uint8_t g_sys_sco_transmit_mode;
+ uint8_t audio_rfu_b1;
+ uint8_t audio_rfu_b2;
+ uint8_t audio_rfu_b3;
+ uint32_t audio_rfu_w[2];
+ uint8_t g_sys_sleep_in_standby_supported;
+ uint8_t g_sys_sleep_master_supported;
+ uint8_t g_sys_sleep_slave_supported;
+ uint8_t power_rfu_b1;
+ uint32_t power_rfu_w[2];
+ uint32_t win_ext;
+ uint8_t edr_tx_edr_delay;
+ uint8_t edr_rx_edr_delay;
+ uint8_t tx_delay;
+ uint8_t rx_delay;
+ uint32_t bb_rfu_w[2];
+ uint8_t agc_mode;
+ uint8_t diff_or_eq;
+ uint8_t ramp_mode;
+ uint8_t modem_rfu_b1;
+ uint32_t modem_rfu_w[2];
+ uint32_t BQB_BitMask_1;
+ uint32_t BQB_BitMask_2;
+ uint16_t bt_coex_threshold[8];
+ uint32_t other_rfu_w[6];
+} pskey_config_t;
+
+typedef struct {
+ uint16_t g_GainValue_A[6];
+ uint16_t g_ClassicPowerValue_A[10];
+ uint16_t g_LEPowerValue_A[16];
+ uint16_t g_BRChannelpwrvalue_A[8];
+ uint16_t g_EDRChannelpwrvalue_A[8];
+ uint16_t g_LEChannelpwrvalue_A[8];
+ uint16_t g_GainValue_B[6];
+ uint16_t g_ClassicPowerValue_B[10];
+ uint16_t g_LEPowerValue_B[16];
+ uint16_t g_BRChannelpwrvalue_B[8];
+ uint16_t g_EDRChannelpwrvalue_B[8];
+ uint16_t g_LEChannelpwrvalue_B[8];
+ uint16_t LE_fix_powerword;
+ uint8_t Classic_pc_by_channel;
+ uint8_t LE_pc_by_channel;
+ uint8_t RF_switch_mode;
+ uint8_t Data_Capture_Mode;
+ uint8_t Analog_IQ_Debug_Mode;
+ uint8_t RF_common_rfu_b3;
+ uint32_t RF_common_rfu_w[5];
+} rf_config_t;
+
+typedef struct {
+ const char *conf_entry;
+ conf_action_t *p_action;
+ void *buf;
+ int len;
+ int size;
+} conf_entry_t;
+
+static uint8_t local_bdaddr[6]={0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
+static pskey_config_t marlin3_pskey;
+static rf_config_t marlin3_rf_config;
+static int s_bt_fd = -1;
+
+static const conf_entry_t marlin3_pksey_table[] = {
+ CONF_ITEM_TABLE(device_class, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(feature_set, 0, marlin3_pskey, 16),
+ CONF_ITEM_TABLE(device_addr, 0, marlin3_pskey, 6),
+ CONF_ITEM_TABLE(comp_id, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_uart0_communication_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(cp2_log_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(LogLevel, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_central_or_perpheral, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(Log_BitMask, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(super_ssp_enable, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(le_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lmp_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lc_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_wbs_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_wbs_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sco_transmit_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_sys_sleep_in_standby_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_master_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_slave_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(win_ext, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_tx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_rx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(tx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(rx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bb_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(agc_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(diff_or_eq, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(ramp_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(BQB_BitMask_1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(BQB_BitMask_2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bt_coex_threshold, 0, marlin3_pskey, 8),
+ CONF_ITEM_TABLE(other_rfu_w, 0, marlin3_pskey, 6),
+ {0, 0, 0, 0, 0}
+};
+
+static const conf_entry_t marlin3_rf_table[] = {
+ CONF_ITEM_TABLE(g_GainValue_A, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_A, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_A, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_GainValue_B, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_B, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_B, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(LE_fix_powerword, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Classic_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(LE_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_switch_mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Data_Capture_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Analog_IQ_Debug_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_b3, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_w, 0, marlin3_rf_config, 5),
+ {0, 0, 0, 0, 0}
+};
+
+static void log_bin_to_hexstr(uint8_t *bin, uint8_t binsz, const char *log_tag)
+{
+ SPRD_DBG("%s", log_tag);
+ SPRD_DUMP(bin, binsz);
+}
+
+static void parse_number(char *p_conf_name, char *p_conf_value, void *buf, int len, int size)
+{
+ uint8_t *dest = (uint8_t *)buf;
+ char *sub_value, *p;
+ uint32_t value;
+ (void)p_conf_name;
+ sub_value = strtok_r(p_conf_value, CONF_VALUES_PARTITION, &p);
+ do {
+ if (sub_value == NULL)
+ break;
+
+ if (sub_value[0] == '0' && (sub_value[1] == 'x' || sub_value[1] == 'X'))
+ value = strtoul(sub_value, 0, 16) & 0xFFFFFFFF;
+ else
+ value = strtoul(sub_value, 0, 10) & 0xFFFFFFFF;
+
+ switch (size) {
+ case sizeof(uint8_t):
+ *dest = value & 0xFF;
+ dest += size;
+ break;
+
+ case sizeof(uint16_t):
+ *((uint16_t *)dest) = value & 0xFFFF;
+ dest += size;
+ break;
+
+ case sizeof(uint32_t):
+ *((uint32_t *)dest) = value & 0xFFFFFFFF;
+ dest += size;
+ break;
+
+ default:
+ break;
+ }
+ sub_value = strtok_r(NULL, CONF_VALUES_PARTITION, &p);
+ } while (--len);
+}
+
+static unsigned char compare_char(unsigned char ch)
+{
+ unsigned char data = 0x0;
+
+ switch(ch)
+ {
+ case 0:
+ case '0':
+ data = 0x0;
+ break;
+ case 1:
+ case '1':
+ data = 0x1;
+ break;
+ case 2:
+ case '2':
+ data = 0x2;
+ break;
+ case 3:
+ case '3':
+ data = 0x3;
+ break;
+ case 4:
+ case '4':
+ data = 0x4;
+ break;
+ case 5:
+ case '5':
+ data = 0x5;
+ break;
+ case 6:
+ case '6':
+ data = 0x6;
+ break;
+ case 7:
+ case '7':
+ data = 0x7;
+ break;
+ case 8:
+ case '8':
+ data = 0x8;
+ break;
+ case 9:
+ case '9':
+ data = 0x9;
+ break;
+ case 10:
+ case 'a':
+ case 'A':
+ data = 0xA;
+ break;
+ case 11:
+ case 'b':
+ case 'B':
+ data = 0xB;
+ break;
+ case 12:
+ case 'c':
+ case 'C':
+ data = 0xC;
+ break;
+ case 13:
+ case 'd':
+ case 'D':
+ data = 0xD;
+ break;
+ case 14:
+ case 'e':
+ case 'E':
+ data = 0xE;
+ break;
+ case 15:
+ case 'f':
+ case 'F':
+ data = 0xF;
+ break;
+ }
+ return data;
+}
+
+static void set_mac_address(uint8_t *addr)
+{
+ int i = 0;
+ unsigned char buff[255];
+ unsigned char tmp[5];
+ unsigned char str, str2;
+
+ FILE *fp = fopen("/sys/class/addr_mgt/addr_bt", "r");
+
+ SPRD_DBG("%s", __func__);
+
+ fscanf(fp, "%s", buff);
+ fclose(fp);
+
+ for (i=0; i<6; i++)
+ {
+ sprintf(tmp, "%c%c", buff[3*i], buff[3*i+1]);
+ str = compare_char(tmp[0]);
+ str2 = compare_char(tmp[1]);
+ local_bdaddr[i] = (str << 4) | str2;
+ }
+
+ for (i = 0; i < 6; i++)
+ addr[5-i] = (unsigned char)local_bdaddr[i];
+}
+
+static void vnd_load_configure(const char *p_path, const conf_entry_t *entry)
+{
+ FILE *p_file;
+ char *p_name, *p_value, *p;
+ conf_entry_t *p_entry;
+ char line[CONF_MAX_LINE_LEN + 1]; /* add 1 for \0 char */
+
+ SPRD_DBG("Attempt to load conf from %s", p_path);
+
+ if ((p_file = fopen(p_path, "r")) != NULL) {
+ /* read line by line */
+ while (fgets(line, CONF_MAX_LINE_LEN + 1, p_file) != NULL) {
+ if (line[0] == CONF_COMMENT) continue;
+
+ p_name = strtok_r(line, CONF_DELIMITERS, &p);
+
+ if (NULL == p_name) {
+ continue;
+ }
+
+ p_value = strtok_r(NULL, CONF_VALUES_DELIMITERS, &p);
+
+ if (NULL == p_value) {
+ SPRD_DBG("vnd_load_conf: missing value for name: %s", p_name);
+ continue;
+ }
+
+ p_entry = (conf_entry_t*)entry;
+
+ while (p_entry->conf_entry != NULL) {
+ if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0) {
+ if (p_entry->p_action) {
+ p_entry->p_action(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ } else {
+ SPRD_DBG("%s -> %s", p_name, p_value);
+ parse_number(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ }
+ break;
+ }
+
+ p_entry++;
+ }
+ }
+
+ fclose(p_file);
+ } else {
+ SPRD_DBG("vnd_load_conf file >%s< not found", p_path);
+ }
+}
+
+static size_t H4Protocol_Send(uint8_t type, const uint8_t* data, size_t length)
+{
+ struct iovec iov[] = {
+ {&type, sizeof(type)},
+ {(uint8_t *)data, length}};
+
+ ssize_t ret = 0;
+ do {
+ ret = writev(s_bt_fd, iov, sizeof(iov) / sizeof(iov[0]));
+ } while (-1 == ret && EAGAIN == errno);
+
+ if (ret == -1) {
+ SPRD_ERR("%s error writing to UART (%s)", __func__, strerror(errno));
+ } else if (ret < length + 1) {
+ SPRD_ERR("%s: %d / %d bytes written - something went wrong...", __func__, ret, length + 1);
+ }
+
+ return ret;
+}
+
+static void *bt_vendor_alloc(int size)
+{
+ void *p = (uint8_t *)malloc(size);
+ return p;
+}
+
+static void bt_vendor_free(void *buffer)
+{
+ free(buffer);
+}
+
+static uint8_t bt_vendor_xmit(uint16_t opcode, void* buffer, hci_cback callback)
+{
+ uint8_t type = HCI_PACKET_TYPE_COMMAND;
+ (void)opcode;
+ HC_BT_HDR* bt_hdr = (HC_BT_HDR *)buffer;
+ H4Protocol_Send(type, bt_hdr->data, bt_hdr->len);
+ return BT_VND_OP_RESULT_SUCCESS;
+}
+
+static uint8_t sprd_vnd_send_hci_vsc(uint16_t cmd, uint8_t *payload, uint8_t len, hci_cback cback)
+{
+ HC_BT_HDR *p_buf;
+ uint8_t *p, ret;
+
+ p_buf = (HC_BT_HDR *)bt_vendor_alloc(
+ BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + len);
+ if (p_buf) {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + len;
+ p = (uint8_t *)(p_buf + 1);
+
+ UINT16_TO_STREAM(p, cmd);
+ *p++ = len;
+ memcpy(p, payload, len);
+ log_bin_to_hexstr((uint8_t *)(p_buf + 1), HCI_CMD_PREAMBLE_SIZE + len, __FUNCTION__);
+ ret = bt_vendor_xmit(cmd, p_buf, cback);
+ bt_vendor_free(p_buf);
+ return ret;
+ }
+ return BT_VND_OP_RESULT_FAIL;
+}
+
+static void hw_core_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+ uint8_t *p, status;
+ uint16_t opcode, mode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+ STREAM_TO_UINT16(mode,p);
+ STREAM_TO_UINT8(status,p);
+ SPRD_DBG("%s hw_core_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ bt_vendor_free(p_evt_buf);
+}
+
+static void hw_core_enable(unsigned char enable)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ p = msg_req;
+ UINT16_TO_STREAM(p, DUAL_MODE);
+ UINT8_TO_STREAM(p, enable ? ENABLE_BT : DISABLE_BT);
+ sprd_vnd_send_hci_vsc(HCI_VSC_ENABLE_COMMMAND, msg_req, (uint8_t)(p - msg_req), NULL);
+}
+
+static void hw_rf_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem, len;
+ uint8_t *p, status;
+ uint16_t opcode, mode = 0;
+
+ p = (uint8_t *)(p_evt_buf + 1) + 1;
+ STREAM_TO_UINT8(len, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+ if (len == 6)
+ STREAM_TO_UINT16(mode, p);
+
+ STREAM_TO_UINT8(status, p);
+
+ SPRD_DBG("%s hw_rf_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_rf_preload()
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+
+ SPRD_DBG("yujian.qin %s", __FUNCTION__);
+ p = msg_req;
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_A[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_A[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_B[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_B[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_B[i]);
+
+ UINT16_TO_STREAM(p, marlin3_rf_config.LE_fix_powerword);
+
+ UINT8_TO_STREAM(p, marlin3_rf_config.Classic_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.LE_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_switch_mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Data_Capture_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Analog_IQ_Debug_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_b3);
+
+ for (i = 0; i < 5; i++)
+ UINT32_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_RF_PARA, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+static void marlin3_pskey_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+
+ uint16_t opcode, node, year;
+ uint8_t *p, month, day;
+ (void)opcode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + FW_NODE_BYTE;
+ STREAM_TO_UINT16(node, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_Y_BYTE;
+ STREAM_TO_UINT16(year, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_M_BYTE;
+ STREAM_TO_UINT8(month, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_D_BYTE;
+ STREAM_TO_UINT8(day, p);
+
+ SPRD_DBG("Bluetooth Firmware Node: %04X Date: %04x-%02x-%02x", node, year, month, day);
+
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_pskey_preload(void *arg)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+ (void)arg;
+
+ SPRD_DBG("%s", __FUNCTION__);
+ p = msg_req;
+ UINT32_TO_STREAM(p, marlin3_pskey.device_class);
+
+ for (i = 0; i < 16; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.feature_set[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.device_addr[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.comp_id);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_uart0_communication_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.cp2_log_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.LogLevel);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_central_or_perpheral);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.Log_BitMask);
+ UINT8_TO_STREAM(p, marlin3_pskey.super_ssp_enable);
+ UINT8_TO_STREAM(p, marlin3_pskey.common_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.common_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.le_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lmp_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lc_rfu_w[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_118);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_118);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sco_transmit_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b1);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b2);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.audio_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_in_standby_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_master_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_slave_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.power_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.power_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.win_ext);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_tx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_rx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.tx_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.rx_delay);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.bb_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.agc_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.diff_or_eq);
+ UINT8_TO_STREAM(p, marlin3_pskey.ramp_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.modem_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.modem_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_1);
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_2);
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_pskey.bt_coex_threshold[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.other_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_PSKEY, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+
+int sprd_config_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ uint8_t *recv = NULL;
+ int len = 0;
+
+ s_bt_fd = fd;
+
+ memset(&marlin3_pskey, 0, sizeof(marlin3_pskey));
+ memset(&marlin3_rf_config, 0, sizeof(marlin3_rf_config));
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_pskey.ini", &marlin3_pksey_table[0]);
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_rf.ini", &marlin3_rf_table[0]);
+ set_mac_address(marlin3_pskey.device_addr);
+
+ marlin3_pskey_preload(NULL);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ marlin3_pskey_cback(recv);
+
+ marlin3_rf_preload();
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_rf_cback(recv);
+
+ hw_core_enable(1);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_core_cback(recv);
+
+ return 0;
+}
+
+int sprd_config_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ SPRD_DBG("Done setting line discpline");
+ return 0;
+}
+
diff --git a/external/cache/sources/hcitools/hciattach_sprd_2.c b/external/cache/sources/hcitools/hciattach_sprd_2.c
new file mode 100755
index 0000000..ce621b7
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_sprd_2.c
@@ -0,0 +1,809 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "hciattach.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+#define LOG_STR "SPRD Bluetooth"
+#define DBG_ON 1
+
+#define SPRD_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n" , LOG_STR, ##arg); \
+ } while(0)
+
+#define SPRD_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror(LOG_STR" ERROR reason"); \
+ } while(0)
+
+#define SPRD_DUMP(buffer, len) \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ do { \
+ int i = 0; \
+ for (i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+#define CONF_ITEM_TABLE(ITEM, ACTION, BUF, LEN) \
+ { #ITEM, ACTION, &(BUF.ITEM), LEN, (sizeof(BUF.ITEM) / LEN) }
+
+#define UINT8_TO_STREAM(p, u8) \
+ { *(p)++ = (uint8_t)(u8); }
+
+#define STREAM_TO_UINT8(u8, p) \
+ { \
+ (u8) = (uint8_t)(*(p)); \
+ (p) += 1; \
+ }
+
+#define UINT16_TO_STREAM(p, u16) \
+ { \
+ *(p)++ = (uint8_t)(u16); \
+ *(p)++ = (uint8_t)((u16) >> 8); \
+ }
+
+#define STREAM_TO_UINT16(u16, p) \
+ { \
+ (u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
+ (p) += 2; \
+ }
+
+#define UINT32_TO_STREAM(p, u32) \
+ { \
+ *(p)++ = (uint8_t)(u32); \
+ *(p)++ = (uint8_t)((u32) >> 8); \
+ *(p)++ = (uint8_t)((u32) >> 16); \
+ *(p)++ = (uint8_t)((u32) >> 24); \
+ }
+
+#define CONF_COMMENT '#'
+#define CONF_DELIMITERS " =\n\r\t"
+#define CONF_VALUES_DELIMITERS "=\n\r\t#"
+#define CONF_VALUES_PARTITION " ,=\n\r\t#"
+#define CONF_MAX_LINE_LEN 255
+
+#define HCI_PSKEY 0xFCA0
+#define HCI_VSC_ENABLE_COMMMAND 0xFCA1
+#define HCI_RF_PARA 0xFCA2
+
+#define RESPONSE_LENGTH 100
+#define HCI_CMD_MAX_LEN 258
+#define HCI_EVT_CMD_CMPL_OPCODE 3
+#define HCI_PACKET_TYPE_COMMAND 1
+#define HCI_CMD_PREAMBLE_SIZE 3
+
+#define FW_NODE_BYTE 6
+#define FW_DATE_D_BYTE 8
+#define FW_DATE_M_BYTE 9
+#define FW_DATE_Y_BYTE 10
+
+#define BT_CONFIG_PATH "/lib/firmware"
+#define BT_HC_HDR_SIZE (sizeof(HC_BT_HDR))
+#define BT_VND_OP_RESULT_SUCCESS 0
+#define BT_VND_OP_RESULT_FAIL 1
+#define MSG_STACK_TO_HC_HCI_CMD 0x2000
+#define START_STOP_CMD_SIZE 3
+#define DUAL_MODE 0
+#define DISABLE_BT 0
+#define ENABLE_BT 1
+
+typedef void (*hci_cback)(void *);
+typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value, void *buf, int len, int size);
+
+typedef struct {
+ uint16_t event;
+ uint16_t len;
+ uint16_t offset;
+ uint16_t layer_specific;
+ uint8_t data[];
+} HC_BT_HDR;
+
+typedef struct {
+ uint32_t device_class;
+ uint8_t feature_set[16];
+ uint8_t device_addr[6];
+ uint16_t comp_id;
+ uint8_t g_sys_uart0_communication_supported;
+ uint8_t cp2_log_mode;
+ uint8_t LogLevel;
+ uint8_t g_central_or_perpheral;
+ uint16_t Log_BitMask;
+ uint8_t super_ssp_enable;
+ uint8_t common_rfu_b3;
+ uint32_t common_rfu_w[2];
+ uint32_t le_rfu_w[2];
+ uint32_t lmp_rfu_w[2];
+ uint32_t lc_rfu_w[2];
+ uint16_t g_wbs_nv_117;
+ uint16_t g_wbs_nv_118;
+ uint16_t g_nbv_nv_117;
+ uint16_t g_nbv_nv_118;
+ uint8_t g_sys_sco_transmit_mode;
+ uint8_t audio_rfu_b1;
+ uint8_t audio_rfu_b2;
+ uint8_t audio_rfu_b3;
+ uint32_t audio_rfu_w[2];
+ uint8_t g_sys_sleep_in_standby_supported;
+ uint8_t g_sys_sleep_master_supported;
+ uint8_t g_sys_sleep_slave_supported;
+ uint8_t power_rfu_b1;
+ uint32_t power_rfu_w[2];
+ uint32_t win_ext;
+ uint8_t edr_tx_edr_delay;
+ uint8_t edr_rx_edr_delay;
+ uint8_t tx_delay;
+ uint8_t rx_delay;
+ uint32_t bb_rfu_w[2];
+ uint8_t agc_mode;
+ uint8_t diff_or_eq;
+ uint8_t ramp_mode;
+ uint8_t modem_rfu_b1;
+ uint32_t modem_rfu_w[2];
+ uint32_t BQB_BitMask_1;
+ uint32_t BQB_BitMask_2;
+ uint16_t bt_coex_threshold[8];
+ uint32_t other_rfu_w[6];
+} pskey_config_t;
+
+typedef struct {
+ uint16_t g_GainValue_A[6];
+ uint16_t g_ClassicPowerValue_A[10];
+ uint16_t g_LEPowerValue_A[16];
+ uint16_t g_BRChannelpwrvalue_A[8];
+ uint16_t g_EDRChannelpwrvalue_A[8];
+ uint16_t g_LEChannelpwrvalue_A[8];
+ uint16_t g_GainValue_B[6];
+ uint16_t g_ClassicPowerValue_B[10];
+ uint16_t g_LEPowerValue_B[16];
+ uint16_t g_BRChannelpwrvalue_B[8];
+ uint16_t g_EDRChannelpwrvalue_B[8];
+ uint16_t g_LEChannelpwrvalue_B[8];
+ uint16_t LE_fix_powerword;
+ uint8_t Classic_pc_by_channel;
+ uint8_t LE_pc_by_channel;
+ uint8_t RF_switch_mode;
+ uint8_t Data_Capture_Mode;
+ uint8_t Analog_IQ_Debug_Mode;
+ uint8_t RF_common_rfu_b3;
+ uint32_t RF_common_rfu_w[5];
+} rf_config_t;
+
+typedef struct {
+ const char *conf_entry;
+ conf_action_t *p_action;
+ void *buf;
+ int len;
+ int size;
+} conf_entry_t;
+
+static uint8_t local_bdaddr[6]={0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
+static pskey_config_t marlin3_pskey;
+static rf_config_t marlin3_rf_config;
+static int s_bt_fd = -1;
+
+static const conf_entry_t marlin3_pksey_table[] = {
+ CONF_ITEM_TABLE(device_class, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(feature_set, 0, marlin3_pskey, 16),
+ CONF_ITEM_TABLE(device_addr, 0, marlin3_pskey, 6),
+ CONF_ITEM_TABLE(comp_id, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_uart0_communication_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(cp2_log_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(LogLevel, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_central_or_perpheral, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(Log_BitMask, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(super_ssp_enable, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(le_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lmp_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lc_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_wbs_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_wbs_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sco_transmit_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_sys_sleep_in_standby_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_master_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_slave_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(win_ext, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_tx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_rx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(tx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(rx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bb_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(agc_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(diff_or_eq, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(ramp_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(BQB_BitMask_1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(BQB_BitMask_2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bt_coex_threshold, 0, marlin3_pskey, 8),
+ CONF_ITEM_TABLE(other_rfu_w, 0, marlin3_pskey, 6),
+ {0, 0, 0, 0, 0}
+};
+
+static const conf_entry_t marlin3_rf_table[] = {
+ CONF_ITEM_TABLE(g_GainValue_A, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_A, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_A, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_GainValue_B, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_B, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_B, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(LE_fix_powerword, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Classic_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(LE_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_switch_mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Data_Capture_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Analog_IQ_Debug_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_b3, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_w, 0, marlin3_rf_config, 5),
+ {0, 0, 0, 0, 0}
+};
+
+static void log_bin_to_hexstr(uint8_t *bin, uint8_t binsz, const char *log_tag)
+{
+ SPRD_DBG("%s", log_tag);
+ SPRD_DUMP(bin, binsz);
+}
+
+static void parse_number(char *p_conf_name, char *p_conf_value, void *buf, int len, int size)
+{
+ uint8_t *dest = (uint8_t *)buf;
+ char *sub_value, *p;
+ uint32_t value;
+ (void)p_conf_name;
+ sub_value = strtok_r(p_conf_value, CONF_VALUES_PARTITION, &p);
+ do {
+ if (sub_value == NULL)
+ break;
+
+ if (sub_value[0] == '0' && (sub_value[1] == 'x' || sub_value[1] == 'X'))
+ value = strtoul(sub_value, 0, 16) & 0xFFFFFFFF;
+ else
+ value = strtoul(sub_value, 0, 10) & 0xFFFFFFFF;
+
+ switch (size) {
+ case sizeof(uint8_t):
+ *dest = value & 0xFF;
+ dest += size;
+ break;
+
+ case sizeof(uint16_t):
+ *((uint16_t *)dest) = value & 0xFFFF;
+ dest += size;
+ break;
+
+ case sizeof(uint32_t):
+ *((uint32_t *)dest) = value & 0xFFFFFFFF;
+ dest += size;
+ break;
+
+ default:
+ break;
+ }
+ sub_value = strtok_r(NULL, CONF_VALUES_PARTITION, &p);
+ } while (--len);
+}
+
+static unsigned char compare_char(unsigned char ch)
+{
+ unsigned char data = 0x0;
+
+ switch(ch)
+ {
+ case 0:
+ case '0':
+ data = 0x0;
+ break;
+ case 1:
+ case '1':
+ data = 0x1;
+ break;
+ case 2:
+ case '2':
+ data = 0x2;
+ break;
+ case 3:
+ case '3':
+ data = 0x3;
+ break;
+ case 4:
+ case '4':
+ data = 0x4;
+ break;
+ case 5:
+ case '5':
+ data = 0x5;
+ break;
+ case 6:
+ case '6':
+ data = 0x6;
+ break;
+ case 7:
+ case '7':
+ data = 0x7;
+ break;
+ case 8:
+ case '8':
+ data = 0x8;
+ break;
+ case 9:
+ case '9':
+ data = 0x9;
+ break;
+ case 10:
+ case 'a':
+ case 'A':
+ data = 0xA;
+ break;
+ case 11:
+ case 'b':
+ case 'B':
+ data = 0xB;
+ break;
+ case 12:
+ case 'c':
+ case 'C':
+ data = 0xC;
+ break;
+ case 13:
+ case 'd':
+ case 'D':
+ data = 0xD;
+ break;
+ case 14:
+ case 'e':
+ case 'E':
+ data = 0xE;
+ break;
+ case 15:
+ case 'f':
+ case 'F':
+ data = 0xF;
+ break;
+ }
+ return data;
+}
+
+static void set_mac_address(uint8_t *addr)
+{
+ int i = 0;
+
+ FILE *fp = fopen("/sys/class/net/wlan0/address", "r");
+ unsigned char buff[255];
+ unsigned char tmp[5];
+ unsigned char str, str2;
+
+ SPRD_DBG("%s", __func__);
+
+ fscanf(fp, "%s", buff);
+ fclose(fp);
+
+ for (i=0; i<6; i++)
+ {
+ sprintf(tmp, "%c%c", buff[3*i], buff[3*i+1]);
+ str = compare_char(tmp[0]);
+ str2 = compare_char(tmp[1]);
+ local_bdaddr[i] = (str << 4) | str2;
+ }
+
+ for (i = 0; i < 6; i++)
+ addr[5-i] = (unsigned char)local_bdaddr[i];
+
+ addr[0] += 1;
+ addr[1] += 1;
+}
+
+static void vnd_load_configure(const char *p_path, const conf_entry_t *entry)
+{
+ FILE *p_file;
+ char *p_name, *p_value, *p;
+ conf_entry_t *p_entry;
+ char line[CONF_MAX_LINE_LEN + 1]; /* add 1 for \0 char */
+
+ SPRD_DBG("Attempt to load conf from %s", p_path);
+
+ if ((p_file = fopen(p_path, "r")) != NULL) {
+ /* read line by line */
+ while (fgets(line, CONF_MAX_LINE_LEN + 1, p_file) != NULL) {
+ if (line[0] == CONF_COMMENT) continue;
+
+ p_name = strtok_r(line, CONF_DELIMITERS, &p);
+
+ if (NULL == p_name) {
+ continue;
+ }
+
+ p_value = strtok_r(NULL, CONF_VALUES_DELIMITERS, &p);
+
+ if (NULL == p_value) {
+ SPRD_DBG("vnd_load_conf: missing value for name: %s", p_name);
+ continue;
+ }
+
+ p_entry = (conf_entry_t*)entry;
+
+ while (p_entry->conf_entry != NULL) {
+ if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0) {
+ if (p_entry->p_action) {
+ p_entry->p_action(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ } else {
+ SPRD_DBG("%s -> %s", p_name, p_value);
+ parse_number(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ }
+ break;
+ }
+
+ p_entry++;
+ }
+ }
+
+ fclose(p_file);
+ } else {
+ SPRD_DBG("vnd_load_conf file >%s< not found", p_path);
+ }
+}
+
+static size_t H4Protocol_Send(uint8_t type, const uint8_t* data, size_t length)
+{
+ struct iovec iov[] = {
+ {&type, sizeof(type)},
+ {(uint8_t *)data, length}};
+
+ ssize_t ret = 0;
+ do {
+ ret = writev(s_bt_fd, iov, sizeof(iov) / sizeof(iov[0]));
+ } while (-1 == ret && EAGAIN == errno);
+
+ if (ret == -1) {
+ SPRD_ERR("%s error writing to UART (%s)", __func__, strerror(errno));
+ } else if (ret < length + 1) {
+ SPRD_ERR("%s: %d / %d bytes written - something went wrong...", __func__, ret, length + 1);
+ }
+
+ return ret;
+}
+
+static void *bt_vendor_alloc(int size)
+{
+ void *p = (uint8_t *)malloc(size);
+ return p;
+}
+
+static void bt_vendor_free(void *buffer)
+{
+ free(buffer);
+}
+
+static uint8_t bt_vendor_xmit(uint16_t opcode, void* buffer, hci_cback callback)
+{
+ uint8_t type = HCI_PACKET_TYPE_COMMAND;
+ (void)opcode;
+ HC_BT_HDR* bt_hdr = (HC_BT_HDR *)buffer;
+ H4Protocol_Send(type, bt_hdr->data, bt_hdr->len);
+ return BT_VND_OP_RESULT_SUCCESS;
+}
+
+static uint8_t sprd_vnd_send_hci_vsc(uint16_t cmd, uint8_t *payload, uint8_t len, hci_cback cback)
+{
+ HC_BT_HDR *p_buf;
+ uint8_t *p, ret;
+
+ p_buf = (HC_BT_HDR *)bt_vendor_alloc(
+ BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + len);
+ if (p_buf) {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + len;
+ p = (uint8_t *)(p_buf + 1);
+
+ UINT16_TO_STREAM(p, cmd);
+ *p++ = len;
+ memcpy(p, payload, len);
+ log_bin_to_hexstr((uint8_t *)(p_buf + 1), HCI_CMD_PREAMBLE_SIZE + len, __FUNCTION__);
+ ret = bt_vendor_xmit(cmd, p_buf, cback);
+ bt_vendor_free(p_buf);
+ return ret;
+ }
+ return BT_VND_OP_RESULT_FAIL;
+}
+
+static void hw_core_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+ uint8_t *p, status;
+ uint16_t opcode, mode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+ STREAM_TO_UINT16(mode,p);
+ STREAM_TO_UINT8(status,p);
+ SPRD_DBG("%s hw_core_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ bt_vendor_free(p_evt_buf);
+}
+
+static void hw_core_enable(unsigned char enable)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ p = msg_req;
+ UINT16_TO_STREAM(p, DUAL_MODE);
+ UINT8_TO_STREAM(p, enable ? ENABLE_BT : DISABLE_BT);
+ sprd_vnd_send_hci_vsc(HCI_VSC_ENABLE_COMMMAND, msg_req, (uint8_t)(p - msg_req), NULL);
+}
+
+static void hw_rf_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem, len;
+ uint8_t *p, status;
+ uint16_t opcode, mode = 0;
+
+ p = (uint8_t *)(p_evt_buf + 1) + 1;
+ STREAM_TO_UINT8(len, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+ if (len == 6)
+ STREAM_TO_UINT16(mode, p);
+
+ STREAM_TO_UINT8(status, p);
+
+ SPRD_DBG("%s hw_rf_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_rf_preload()
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+
+ SPRD_DBG("yujian.qin %s", __FUNCTION__);
+ p = msg_req;
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_A[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_A[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_B[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_B[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_B[i]);
+
+ UINT16_TO_STREAM(p, marlin3_rf_config.LE_fix_powerword);
+
+ UINT8_TO_STREAM(p, marlin3_rf_config.Classic_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.LE_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_switch_mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Data_Capture_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Analog_IQ_Debug_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_b3);
+
+ for (i = 0; i < 5; i++)
+ UINT32_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_RF_PARA, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+static void marlin3_pskey_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+
+ uint16_t opcode, node, year;
+ uint8_t *p, month, day;
+ (void)opcode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + FW_NODE_BYTE;
+ STREAM_TO_UINT16(node, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_Y_BYTE;
+ STREAM_TO_UINT16(year, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_M_BYTE;
+ STREAM_TO_UINT8(month, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_D_BYTE;
+ STREAM_TO_UINT8(day, p);
+
+ SPRD_DBG("Bluetooth Firmware Node: %04X Date: %04x-%02x-%02x", node, year, month, day);
+
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_pskey_preload(void *arg)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+ (void)arg;
+
+ SPRD_DBG("%s", __FUNCTION__);
+ p = msg_req;
+ UINT32_TO_STREAM(p, marlin3_pskey.device_class);
+
+ for (i = 0; i < 16; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.feature_set[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.device_addr[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.comp_id);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_uart0_communication_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.cp2_log_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.LogLevel);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_central_or_perpheral);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.Log_BitMask);
+ UINT8_TO_STREAM(p, marlin3_pskey.super_ssp_enable);
+ UINT8_TO_STREAM(p, marlin3_pskey.common_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.common_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.le_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lmp_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lc_rfu_w[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_118);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_118);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sco_transmit_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b1);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b2);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.audio_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_in_standby_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_master_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_slave_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.power_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.power_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.win_ext);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_tx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_rx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.tx_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.rx_delay);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.bb_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.agc_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.diff_or_eq);
+ UINT8_TO_STREAM(p, marlin3_pskey.ramp_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.modem_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.modem_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_1);
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_2);
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_pskey.bt_coex_threshold[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.other_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_PSKEY, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+
+int sprd_config_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ uint8_t *recv = NULL;
+ int len = 0;
+
+ s_bt_fd = fd;
+
+ memset(&marlin3_pskey, 0, sizeof(marlin3_pskey));
+ memset(&marlin3_rf_config, 0, sizeof(marlin3_rf_config));
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_pskey.ini", &marlin3_pksey_table[0]);
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_rf.ini", &marlin3_rf_table[0]);
+ set_mac_address(marlin3_pskey.device_addr);
+
+ marlin3_pskey_preload(NULL);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ marlin3_pskey_cback(recv);
+
+ marlin3_rf_preload();
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_rf_cback(recv);
+
+ hw_core_enable(1);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_core_cback(recv);
+
+ return 0;
+}
+
+int sprd_config_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ SPRD_DBG("Done setting line discpline");
+ return 0;
+}
+
diff --git a/external/cache/sources/hcitools/hciattach_st.c b/external/cache/sources/hcitools/hciattach_st.c
new file mode 100644
index 0000000..dbb7c47
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_st.c
@@ -0,0 +1,278 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "hciattach.h"
+
+static int debug = 0;
+
+static int do_command(int fd, uint8_t ogf, uint16_t ocf,
+ uint8_t *cparam, int clen, uint8_t *rparam, int rlen)
+{
+ //uint16_t opcode = (uint16_t) ((ocf & 0x03ff) | (ogf << 10));
+ unsigned char cp[260], rp[260];
+ int len, size, offset = 3;
+
+ cp[0] = 0x01;
+ cp[1] = ocf & 0xff;
+ cp[2] = ogf << 2 | ocf >> 8;
+ cp[3] = clen;
+
+ if (clen > 0)
+ memcpy(cp + 4, cparam, clen);
+
+ if (debug) {
+ int i;
+ printf("[<");
+ for (i = 0; i < clen + 4; i++)
+ printf(" %02x", cp[i]);
+ printf("]\n");
+ }
+
+ if (write(fd, cp, clen + 4) < 0)
+ return -1;
+
+ do {
+ if (read(fd, rp, 1) < 1)
+ return -1;
+ } while (rp[0] != 0x04);
+
+ if (read(fd, rp + 1, 2) < 2)
+ return -1;
+
+ do {
+ len = read(fd, rp + offset, sizeof(rp) - offset);
+ offset += len;
+ } while (offset < rp[2] + 3);
+
+ if (debug) {
+ int i;
+ printf("[>");
+ for (i = 0; i < offset; i++)
+ printf(" %02x", rp[i]);
+ printf("]\n");
+ }
+
+ if (rp[0] != 0x04) {
+ errno = EIO;
+ return -1;
+ }
+
+ switch (rp[1]) {
+ case 0x0e: /* command complete */
+ if (rp[6] != 0x00)
+ return -ENXIO;
+ offset = 3 + 4;
+ size = rp[2] - 4;
+ break;
+ case 0x0f: /* command status */
+ /* fall through */
+ default:
+ offset = 3;
+ size = rp[2];
+ break;
+ }
+
+ if (!rparam || rlen < size)
+ return -ENXIO;
+
+ memcpy(rparam, rp + offset, size);
+
+ return size;
+}
+
+static int load_file(int dd, uint16_t version, const char *suffix)
+{
+ DIR *dir;
+ struct dirent *d;
+ char pathname[PATH_MAX], filename[NAME_MAX], prefix[20];
+ unsigned char cmd[256];
+ unsigned char buf[256];
+ uint8_t seqnum = 0;
+ int fd, size, len, found_fw_file;
+
+ memset(filename, 0, sizeof(filename));
+
+ snprintf(prefix, sizeof(prefix), "STLC2500_R%d_%02d_",
+ version >> 8, version & 0xff);
+
+ strcpy(pathname, "/lib/firmware");
+ dir = opendir(pathname);
+ if (!dir) {
+ strcpy(pathname, ".");
+ dir = opendir(pathname);
+ if (!dir)
+ return -errno;
+ }
+
+ found_fw_file = 0;
+ while (1) {
+ d = readdir(dir);
+ if (!d)
+ break;
+
+ if (strncmp(d->d_name + strlen(d->d_name) - strlen(suffix),
+ suffix, strlen(suffix)))
+ continue;
+
+ if (strncmp(d->d_name, prefix, strlen(prefix)))
+ continue;
+
+ snprintf(filename, sizeof(filename), "%s/%s",
+ pathname, d->d_name);
+ found_fw_file = 1;
+ }
+
+ closedir(dir);
+
+ if (!found_fw_file)
+ return -ENOENT;
+
+ printf("Loading file %s\n", filename);
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror("Can't open firmware file");
+ return -errno;
+ }
+
+ while (1) {
+ size = read(fd, cmd + 1, 254);
+ if (size <= 0)
+ break;
+
+ cmd[0] = seqnum;
+
+ len = do_command(dd, 0xff, 0x002e, cmd, size + 1, buf, sizeof(buf));
+ if (len < 1)
+ break;
+
+ if (buf[0] != seqnum) {
+ fprintf(stderr, "Sequence number mismatch\n");
+ break;
+ }
+
+ seqnum++;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+int stlc2500_init(int dd, bdaddr_t *bdaddr)
+{
+ unsigned char cmd[16];
+ unsigned char buf[254];
+ uint16_t version;
+ int len;
+ int err;
+
+ /* Hci_Cmd_Ericsson_Read_Revision_Information */
+ len = do_command(dd, 0xff, 0x000f, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ printf("%s\n", buf);
+
+ /* HCI_Read_Local_Version_Information */
+ len = do_command(dd, 0x04, 0x0001, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ version = buf[2] << 8 | buf[1];
+
+ err = load_file(dd, version, ".ptc");
+ if (err < 0) {
+ if (err == -ENOENT)
+ fprintf(stderr, "No ROM patch file loaded.\n");
+ else
+ return -1;
+ }
+
+ err = load_file(dd, buf[2] << 8 | buf[1], ".ssf");
+ if (err < 0) {
+ if (err == -ENOENT)
+ fprintf(stderr, "No static settings file loaded.\n");
+ else
+ return -1;
+ }
+
+ cmd[0] = 0xfe;
+ cmd[1] = 0x06;
+ bacpy((bdaddr_t *) (cmd + 2), bdaddr);
+
+ /* Hci_Cmd_ST_Store_In_NVDS */
+ len = do_command(dd, 0xff, 0x0022, cmd, 8, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ /* HCI_Reset : applies parameters*/
+ len = do_command(dd, 0x03, 0x0003, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ return 0;
+}
+
+int bgb2xx_init(int dd, bdaddr_t *bdaddr)
+{
+ unsigned char cmd[16];
+ unsigned char buf[254];
+ int len;
+
+ len = do_command(dd, 0xff, 0x000f, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ printf("%s\n", buf);
+
+ cmd[0] = 0xfe;
+ cmd[1] = 0x06;
+ bacpy((bdaddr_t *) (cmd + 2), bdaddr);
+
+ len = do_command(dd, 0xff, 0x0022, cmd, 8, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ len = do_command(dd, 0x03, 0x0003, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_ti.c b/external/cache/sources/hcitools/hciattach_ti.c
new file mode 100644
index 0000000..8322b45
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_ti.c
@@ -0,0 +1,533 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#ifdef HCIATTACH_DEBUG
+#define DPRINTF(x...) printf(x)
+#else
+#define DPRINTF(x...)
+#endif
+
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
+
+#define MAKEWORD(a, b) ((uint16_t)(((uint8_t)(a)) | ((uint16_t)((uint8_t)(b))) << 8))
+
+#define TI_MANUFACTURER_ID 13
+
+#define FIRMWARE_DIRECTORY "/lib/firmware/ti-connectivity/"
+
+#define ACTION_SEND_COMMAND 1
+#define ACTION_WAIT_EVENT 2
+#define ACTION_SERIAL 3
+#define ACTION_DELAY 4
+#define ACTION_RUN_SCRIPT 5
+#define ACTION_REMARKS 6
+
+#define BRF_DEEP_SLEEP_OPCODE_BYTE_1 0x0c
+#define BRF_DEEP_SLEEP_OPCODE_BYTE_2 0xfd
+#define BRF_DEEP_SLEEP_OPCODE \
+ (BRF_DEEP_SLEEP_OPCODE_BYTE_1 | (BRF_DEEP_SLEEP_OPCODE_BYTE_2 << 8))
+
+#define FILE_HEADER_MAGIC 0x42535442
+
+/*
+ * BRF Firmware header
+ */
+struct bts_header {
+ uint32_t magic;
+ uint32_t version;
+ uint8_t future[24];
+ uint8_t actions[0];
+}__attribute__ ((packed));
+
+/*
+ * BRF Actions structure
+ */
+struct bts_action {
+ uint16_t type;
+ uint16_t size;
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+struct bts_action_send {
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+struct bts_action_wait {
+ uint32_t msec;
+ uint32_t size;
+ uint8_t data[0];
+}__attribute__ ((packed));
+
+struct bts_action_delay {
+ uint32_t msec;
+}__attribute__ ((packed));
+
+struct bts_action_serial {
+ uint32_t baud;
+ uint32_t flow_control;
+}__attribute__ ((packed));
+
+static FILE *bts_load_script(const char *file_name, uint32_t *version)
+{
+ struct bts_header header;
+ FILE *fp;
+
+ fp = fopen(file_name, "rb");
+ if (!fp) {
+ perror("can't open firmware file");
+ return NULL;
+ }
+
+ if (1 != fread(&header, sizeof(struct bts_header), 1, fp)) {
+ perror("can't read firmware file");
+ goto errclose;
+ }
+
+ if (header.magic != FILE_HEADER_MAGIC) {
+ fprintf(stderr, "%s not a legal TI firmware file\n", file_name);
+ goto errclose;
+ }
+
+ if (NULL != version)
+ *version = header.version;
+
+ return fp;
+
+errclose:
+ fclose(fp);
+
+ return NULL;
+}
+
+static unsigned long bts_fetch_action(FILE *fp, unsigned char *action_buf,
+ unsigned long buf_size, uint16_t *action_type)
+{
+ struct bts_action action_hdr;
+ unsigned long nread;
+
+ if (!fp)
+ return 0;
+
+ if (1 != fread(&action_hdr, sizeof(struct bts_action), 1, fp))
+ return 0;
+
+ if (action_hdr.size > buf_size) {
+ fprintf(stderr, "bts_next_action: not enough space to read next action\n");
+ return 0;
+ }
+
+ nread = fread(action_buf, sizeof(uint8_t), action_hdr.size, fp);
+ if (nread != (action_hdr.size)) {
+ fprintf(stderr, "bts_next_action: fread failed to read next action\n");
+ return 0;
+ }
+
+ *action_type = action_hdr.type;
+
+ return nread * sizeof(uint8_t);
+}
+
+static void bts_unload_script(FILE *fp)
+{
+ if (fp)
+ fclose(fp);
+}
+
+static int is_it_texas(const uint8_t *respond)
+{
+ uint16_t manufacturer_id;
+
+ manufacturer_id = MAKEWORD(respond[11], respond[12]);
+
+ return TI_MANUFACTURER_ID == manufacturer_id ? 1 : 0;
+}
+
+static const char *get_firmware_name(const uint8_t *respond)
+{
+ static char firmware_file_name[PATH_MAX] = {0};
+ uint16_t version = 0, chip = 0, min_ver = 0, maj_ver = 0;
+
+ version = MAKEWORD(respond[13], respond[14]);
+ chip = (version & 0x7C00) >> 10;
+ min_ver = (version & 0x007F);
+ maj_ver = (version & 0x0380) >> 7;
+
+ if (version & 0x8000)
+ maj_ver |= 0x0008;
+
+ sprintf(firmware_file_name, FIRMWARE_DIRECTORY "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
+
+ return firmware_file_name;
+}
+
+static void brf_delay(struct bts_action_delay *delay)
+{
+ usleep(1000 * delay->msec);
+}
+
+static int brf_set_serial_params(struct bts_action_serial *serial_action,
+ int fd, int *speed, struct termios *ti)
+{
+ fprintf(stderr, "texas: changing baud rate to %u, flow control to %u\n",
+ serial_action->baud, serial_action->flow_control );
+ tcflush(fd, TCIOFLUSH);
+
+ if (serial_action->flow_control)
+ ti->c_cflag |= CRTSCTS;
+ else
+ ti->c_cflag &= ~CRTSCTS;
+
+ if (tcsetattr(fd, TCSANOW, ti) < 0) {
+ perror("Can't set port settings");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (set_speed(fd, ti, serial_action->baud) < 0) {
+ perror("Can't set baud rate");
+ return -1;
+ }
+
+ if (speed)
+ *speed = serial_action->baud;
+
+ return 0;
+}
+
+static int brf_send_command_socket(int fd, struct bts_action_send *send_action)
+{
+ char response[1024] = {0};
+ hci_command_hdr *cmd = (hci_command_hdr *) send_action->data;
+ uint16_t opcode = cmd->opcode;
+
+ struct hci_request rq;
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = cmd_opcode_ogf(opcode);
+ rq.ocf = cmd_opcode_ocf(opcode);
+ rq.event = EVT_CMD_COMPLETE;
+ rq.cparam = &send_action->data[3];
+ rq.clen = send_action->data[2];
+ rq.rparam = response;
+ rq.rlen = sizeof(response);
+
+ if (hci_send_req(fd, &rq, 15) < 0) {
+ perror("Cannot send hci command to socket");
+ return -1;
+ }
+
+ /* verify success */
+ if (response[0]) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int brf_send_command_file(int fd, struct bts_action_send *send_action,
+ long size)
+{
+ unsigned char response[1024] = {0};
+ long ret = 0;
+
+ /* send command */
+ if (size != write(fd, send_action, size)) {
+ perror("Texas: Failed to write action command");
+ return -1;
+ }
+
+ /* read response */
+ ret = read_hci_event(fd, response, sizeof(response));
+ if (ret < 0) {
+ perror("texas: failed to read command response");
+ return -1;
+ }
+
+ /* verify success */
+ if (ret < 7 || 0 != response[6]) {
+ fprintf( stderr, "TI init command failed.\n" );
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int brf_send_command(int fd, struct bts_action_send *send_action,
+ long size, int hcill_installed)
+{
+ int ret = 0;
+ char *fixed_action;
+
+ /* remove packet type when giving to socket API */
+ if (hcill_installed) {
+ fixed_action = ((char *) send_action) + 1;
+ ret = brf_send_command_socket(fd, (struct bts_action_send *) fixed_action);
+ } else {
+ ret = brf_send_command_file(fd, send_action, size);
+ }
+
+ return ret;
+}
+
+static int brf_do_action(uint16_t brf_type, uint8_t *brf_action, long brf_size,
+ int fd, int *speed, struct termios *ti, int hcill_installed)
+{
+ int ret = 0;
+
+ switch (brf_type) {
+ case ACTION_SEND_COMMAND:
+ DPRINTF("W");
+ ret = brf_send_command(fd,
+ (struct bts_action_send *) brf_action,
+ brf_size, hcill_installed);
+ break;
+ case ACTION_WAIT_EVENT:
+ DPRINTF("R");
+ break;
+ case ACTION_SERIAL:
+ DPRINTF("S");
+ ret = brf_set_serial_params((struct bts_action_serial *) brf_action, fd, speed, ti);
+ break;
+ case ACTION_DELAY:
+ DPRINTF("D");
+ brf_delay((struct bts_action_delay *) brf_action);
+ break;
+ case ACTION_REMARKS:
+ DPRINTF("C");
+ break;
+ default:
+ fprintf(stderr, "brf_init: unknown firmware action type (%d)\n", brf_type);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * tests whether a given brf action is a HCI_VS_Sleep_Mode_Configurations cmd
+ */
+static int brf_action_is_deep_sleep(uint8_t *brf_action, long brf_size,
+ uint16_t brf_type)
+{
+ uint16_t opcode;
+
+ if (brf_type != ACTION_SEND_COMMAND)
+ return 0;
+
+ if (brf_size < 3)
+ return 0;
+
+ if (brf_action[0] != HCI_COMMAND_PKT)
+ return 0;
+
+ /* HCI data is little endian */
+ opcode = brf_action[1] | (brf_action[2] << 8);
+
+ if (opcode != BRF_DEEP_SLEEP_OPCODE)
+ return 0;
+
+ /* action is deep sleep configuration command ! */
+ return 1;
+}
+
+/*
+ * This function is called twice.
+ * The first time it is called, it loads the brf script, and executes its
+ * commands until it reaches a deep sleep command (or its end).
+ * The second time it is called, it assumes HCILL protocol is set up,
+ * and sends rest of brf script via the supplied socket.
+ */
+static int brf_do_script(int fd, int *speed, struct termios *ti, const char *bts_file)
+{
+ int ret = 0, hcill_installed = bts_file ? 0 : 1;
+ uint32_t vers;
+ static FILE *brf_script_file = NULL;
+ static uint8_t brf_action[512];
+ static long brf_size;
+ static uint16_t brf_type;
+
+ /* is it the first time we are called ? */
+ if (0 == hcill_installed) {
+ DPRINTF("Sending script to serial device\n");
+ brf_script_file = bts_load_script(bts_file, &vers );
+ if (!brf_script_file) {
+ fprintf(stderr, "Warning: cannot find BTS file: %s\n",
+ bts_file);
+ return 0;
+ }
+
+ fprintf( stderr, "Loaded BTS script version %u\n", vers );
+
+ brf_size = bts_fetch_action(brf_script_file, brf_action,
+ sizeof(brf_action), &brf_type);
+ if (brf_size == 0) {
+ fprintf(stderr, "Warning: BTS file is empty !");
+ return 0;
+ }
+ }
+ else {
+ DPRINTF("Sending script to bluetooth socket\n");
+ }
+
+ /* execute current action and continue to parse brf script file */
+ while (brf_size != 0) {
+ ret = brf_do_action(brf_type, brf_action, brf_size,
+ fd, speed, ti, hcill_installed);
+ if (ret == -1)
+ break;
+
+ brf_size = bts_fetch_action(brf_script_file, brf_action,
+ sizeof(brf_action), &brf_type);
+
+ /* if this is the first time we run (no HCILL yet) */
+ /* and a deep sleep command is encountered */
+ /* we exit */
+ if (!hcill_installed &&
+ brf_action_is_deep_sleep(brf_action,
+ brf_size, brf_type))
+ return 0;
+ }
+
+ bts_unload_script(brf_script_file);
+ brf_script_file = NULL;
+ DPRINTF("\n");
+
+ return ret;
+}
+
+int texas_init(int fd, int *speed, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[4];
+ unsigned char resp[100]; /* Response */
+ const char *bts_file;
+ int n;
+
+ memset(resp,'\0', 100);
+
+ /* It is possible to get software version with manufacturer specific
+ HCI command HCI_VS_TI_Version_Number. But the only thing you get more
+ is if this is point-to-point or point-to-multipoint module */
+
+ /* Get Manufacturer and LMP version */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 0) {
+ perror("Failed to write init command (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+ if (n < 4) {
+ fprintf(stderr, "Wanted to write 4 bytes, could only write %d. Stop\n", n);
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+
+ /* Wait for command complete event for our Opcode */
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ /* Verify manufacturer */
+ if (! is_it_texas(resp)) {
+ fprintf(stderr,"ERROR: module's manufacturer is not Texas Instruments\n");
+ return -1;
+ }
+
+ fprintf(stderr, "Found a Texas Instruments' chip!\n");
+
+ bts_file = get_firmware_name(resp);
+ fprintf(stderr, "Firmware file : %s\n", bts_file);
+
+ n = brf_do_script(fd, speed, ti, bts_file);
+
+ nanosleep(&tm, NULL);
+
+ return n;
+}
+
+int texas_post(int fd, struct termios *ti)
+{
+ int dev_id, dd, ret = 0;
+
+ sleep(1);
+
+ dev_id = ioctl(fd, HCIUARTGETDEVICE, 0);
+ if (dev_id < 0) {
+ perror("cannot get device id");
+ return -1;
+ }
+
+ DPRINTF("\nAdded device hci%d\n", dev_id);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("HCI device open failed");
+ return -1;
+ }
+
+ if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) {
+ fprintf(stderr, "Can't init device hci%d: %s (%d)", dev_id,
+ strerror(errno), errno);
+ hci_close_dev(dd);
+ return -1;
+ }
+
+ ret = brf_do_script(dd, NULL, ti, NULL);
+
+ hci_close_dev(dd);
+
+ return ret;
+}
diff --git a/external/cache/sources/hcitools/hciattach_tialt.c b/external/cache/sources/hcitools/hciattach_tialt.c
new file mode 100644
index 0000000..c3caa49
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_tialt.c
@@ -0,0 +1,242 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#define FAILIF(x, args...) do { \
+ if (x) { \
+ fprintf(stderr, ##args); \
+ return -1; \
+ } \
+} while(0)
+
+typedef struct {
+ uint8_t uart_prefix;
+ hci_event_hdr hci_hdr;
+ evt_cmd_complete cmd_complete;
+ uint8_t status;
+ uint8_t data[16];
+} __attribute__((packed)) command_complete_t;
+
+static int read_command_complete(int fd, unsigned short opcode, unsigned char len) {
+ command_complete_t resp;
+ /* Read reply. */
+ FAILIF(read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0,
+ "Failed to read response");
+
+ /* Parse speed-change reply */
+ FAILIF(resp.uart_prefix != HCI_EVENT_PKT,
+ "Error in response: not an event packet, but 0x%02x!\n",
+ resp.uart_prefix);
+
+ FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE, /* event must be event-complete */
+ "Error in response: not a cmd-complete event, "
+ "but 0x%02x!\n", resp.hci_hdr.evt);
+
+ FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */
+ "Error in response: plen is not >= 4, but 0x%02x!\n",
+ resp.hci_hdr.plen);
+
+ /* cmd-complete event: opcode */
+ FAILIF(resp.cmd_complete.opcode != (uint16_t)opcode,
+ "Error in response: opcode is 0x%04x, not 0x%04x!",
+ resp.cmd_complete.opcode, opcode);
+
+ return resp.status == 0 ? 0 : -1;
+}
+
+typedef struct {
+ uint8_t uart_prefix;
+ hci_command_hdr hci_hdr;
+ uint32_t speed;
+} __attribute__((packed)) texas_speed_change_cmd_t;
+
+static int texas_change_speed(int fd, uint32_t speed)
+{
+ return 0;
+}
+
+static int texas_load_firmware(int fd, const char *firmware) {
+
+ int fw = open(firmware, O_RDONLY);
+
+ fprintf(stdout, "Opening firmware file: %s\n", firmware);
+
+ FAILIF(fw < 0,
+ "Could not open firmware file %s: %s (%d).\n",
+ firmware, strerror(errno), errno);
+
+ fprintf(stdout, "Uploading firmware...\n");
+ do {
+ /* Read each command and wait for a response. */
+ unsigned char data[1024];
+ unsigned char cmdp[1 + sizeof(hci_command_hdr)];
+ hci_command_hdr *cmd = (hci_command_hdr *)(cmdp + 1);
+ int nr;
+ nr = read(fw, cmdp, sizeof(cmdp));
+ if (!nr)
+ break;
+ FAILIF(nr != sizeof(cmdp), "Could not read H4 + HCI header!\n");
+ FAILIF(*cmdp != HCI_COMMAND_PKT, "Command is not an H4 command packet!\n");
+
+ FAILIF(read(fw, data, cmd->plen) != cmd->plen,
+ "Could not read %d bytes of data for command with opcode %04x!\n",
+ cmd->plen,
+ cmd->opcode);
+
+ {
+ int nw;
+#if 0
+ fprintf(stdout, "\topcode 0x%04x (%d bytes of data).\n",
+ cmd->opcode,
+ cmd->plen);
+#endif
+ struct iovec iov_cmd[2];
+ iov_cmd[0].iov_base = cmdp;
+ iov_cmd[0].iov_len = sizeof(cmdp);
+ iov_cmd[1].iov_base = data;
+ iov_cmd[1].iov_len = cmd->plen;
+ nw = writev(fd, iov_cmd, 2);
+ FAILIF(nw != (int) sizeof(cmd) + cmd->plen,
+ "Could not send entire command (sent only %d bytes)!\n",
+ nw);
+ }
+
+ /* Wait for response */
+ if (read_command_complete(fd,
+ cmd->opcode,
+ cmd->plen) < 0) {
+ return -1;
+ }
+
+ } while(1);
+ fprintf(stdout, "Firmware upload successful.\n");
+
+ close(fw);
+ return 0;
+}
+
+int texasalt_init(int fd, int speed, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[4];
+ unsigned char resp[100]; /* Response */
+ int n;
+
+ memset(resp,'\0', 100);
+
+ /* It is possible to get software version with manufacturer specific
+ HCI command HCI_VS_TI_Version_Number. But the only thing you get more
+ is if this is point-to-point or point-to-multipoint module */
+
+ /* Get Manufacturer and LMP version */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 0) {
+ perror("Failed to write init command (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+ if (n < 4) {
+ fprintf(stderr, "Wanted to write 4 bytes, could only write %d. Stop\n", n);
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+
+ /* Wait for command complete event for our Opcode */
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ /* Verify manufacturer */
+ if ((resp[11] & 0xFF) != 0x0d)
+ fprintf(stderr,"WARNING : module's manufacturer is not Texas Instrument\n");
+
+ /* Print LMP version */
+ fprintf(stderr, "Texas module LMP version : 0x%02x\n", resp[10] & 0xFF);
+
+ /* Print LMP subversion */
+ {
+ unsigned short lmp_subv = resp[13] | (resp[14] << 8);
+ unsigned short brf_chip = (lmp_subv & 0x7c00) >> 10;
+ static const char *c_brf_chip[8] = {
+ "unknown",
+ "unknown",
+ "brf6100",
+ "brf6150",
+ "brf6300",
+ "brf6350",
+ "unknown",
+ "wl1271"
+ };
+ char fw[100];
+
+ fprintf(stderr, "Texas module LMP sub-version : 0x%04x\n", lmp_subv);
+
+ fprintf(stderr,
+ "\tinternal version freeze: %d\n"
+ "\tsoftware version: %d\n"
+ "\tchip: %s (%d)\n",
+ lmp_subv & 0x7f,
+ ((lmp_subv & 0x8000) >> (15-3)) | ((lmp_subv & 0x380) >> 7),
+ ((brf_chip > 7) ? "unknown" : c_brf_chip[brf_chip]),
+ brf_chip);
+
+ sprintf(fw, "/etc/firmware/%s.bin", c_brf_chip[brf_chip]);
+ texas_load_firmware(fd, fw);
+
+ texas_change_speed(fd, speed);
+ }
+ nanosleep(&tm, NULL);
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_xr.c b/external/cache/sources/hcitools/hciattach_xr.c
new file mode 100644
index 0000000..c42b009
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_xr.c
@@ -0,0 +1,557 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "hciattach.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+#define LOG_STR "XRADIO Bluetooth"
+#define DBG_ON 1
+
+#define XR_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n" , LOG_STR, ##arg); \
+ } while(0)
+
+#define XR_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror(LOG_STR" ERROR reason"); \
+ } while(0)
+
+#define XR_DUMP(buffer, len) \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ do { \
+ for (int i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+#define BT_FW_PATH_NAME "/system/vendor/etc/firmware/fw_xr829_bt.bin"
+#define BT_FW_LOAD_ADDR 0x0000
+#define BT_FW_JUMP_ADDR 0x0000
+#define AW1722 1
+#define AW1732 2
+#define CHIP_NAME AW1722
+
+#define SZ_1K (0x00000400U )
+#define SZ_16K (0x00004000U )
+
+#define SWAP16(d) (((d & 0xff) << 8) | ((d & 0xff00) >> 8))
+#define SWAP32(d) (((d & 0xff) << 24) | ((d & 0xff00) << 8) \
+ | ((d & 0xff0000) >> 8) | ((d & 0xff000000) >> 24))
+
+#define CMD_ID(group, key) (((group) << 3) | (key))
+
+/*----------------------------*/
+/* COMMANDS FORM PC TO MCU */
+/*----------------------------*/
+#define CMD_ID_MEMRW 0x00
+#define CMD_ID_SEQRQ 0x01
+#define CMD_ID_SYSCTL 0x02
+#define CMD_ID_FLASH 0x03
+
+#define CMD_ID_SEQRD CMD_ID(CMD_ID_SEQRQ, 0)
+#define CMD_ID_SEQWR CMD_ID(CMD_ID_SEQRQ, 1)
+/* uart commands */
+#define CMD_ID_SETUART CMD_ID(CMD_ID_SYSCTL, 0)
+#define CMD_ID_SETPC CMD_ID(CMD_ID_SYSCTL, 3)
+
+#define CMD_WRITEN 0
+#define CMD_WRITESEQ 1
+#define CMD_SETBAUD 2
+#define CMD_SETPC 3
+#define DATA_RAW 4
+
+/******************************************************************************
+** Type definitions
+******************************************************************************/
+
+/* vendor serial control block */
+typedef struct
+{
+ int fd; /* fd to Bluetooth device */
+ struct termios *ti; /* serial terminal of BT port */
+} vnd_userial_cb_t;
+
+#pragma pack(1)
+/* command header
+ *
+ * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 byte 6 -7 byte 8-11
+ * ___________________________________________________________________________________________________
+ * | | | | | | | | |
+ * | 'B' | 'R' | 'O' | 'M' | Flags |Reserved | Checksum | Playload Length |
+ * |_________|_________|_________|_________|_________|_________|__________ ________|___________________|
+ */
+typedef struct {
+ uint8_t magic[4]; // magic "BROM"
+ #define CMD_BROM_MAGIC "BROM"
+ uint8_t flags;
+ #define CMD_HFLAG_ERROR (0x1U << 0)
+ #define CMD_HFLAG_ACK (0x1U << 1)
+ #define CMD_HFLAG_CHECK (0x1U << 2)
+ #define CMD_HFLAG_RETRY (0x1U << 3)
+ #define CMD_HFLAG_EXE (0x1U << 4)
+ uint8_t version:4;
+ uint8_t reserved:4;
+ uint16_t checksum;
+ uint32_t payload_len;
+} __attribute__((packed)) cmd_header_t;
+#define MB_CMD_HEADER_SIZE (sizeof(cmd_header_t))
+
+/* acknownledge structure */
+typedef struct {
+ cmd_header_t h;
+ uint8_t err;
+} __attribute__((packed)) cmd_ack_t;
+
+/* sequence read/write command structure */
+typedef struct {
+ cmd_header_t h;
+ uint8_t cmdid;
+ uint32_t addr;
+ uint32_t dlen;
+ uint16_t dcs;
+} __attribute__((packed)) cmd_seq_wr_t;
+
+/* io change command structure */
+typedef struct {
+ cmd_header_t h;
+ uint8_t cmdid;
+ uint32_t val;
+} __attribute__((packed)) cmd_sys_t;
+
+typedef struct {
+ cmd_header_t h;
+ uint8_t cmdid;
+ uint32_t lcr;
+} __attribute__((packed)) cmd_sys_setuart_t;
+
+#pragma pack()
+
+static const uint8_t hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
+static const uint8_t hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x04, 0x60, 0xE3, 0x16, 0x00};
+static vnd_userial_cb_t vnd_userial;
+
+static int32_t cmd_sync_uart(void);
+static int32_t cmd_sync_baud(uint32_t lcr);
+static int32_t cmd_write_seq(uint32_t addr, uint32_t len, uint8_t *data);
+static int32_t cmd_set_pc(uint32_t pc);
+static void userial_set_hw_fctrl(uint8_t hw_fctrl);
+static uint32_t userial_read(uint8_t *p_buffer, uint32_t len, uint32_t timeout);
+static uint32_t userial_write(const uint8_t *p_data, uint32_t len);
+
+/******************************************************************************
+** Functions
+******************************************************************************/
+static uint16_t CheckSum16(uint8_t *data, uint32_t len)
+{
+ uint16_t cs = 0;
+ uint16_t *p = (uint16_t *)data;
+
+ while(len > 1) {
+ cs += *p++;
+ len -= 2;
+ }
+ if (len) {
+ cs += *(uint8_t *)p;
+ }
+ return cs;
+}
+
+static uint64_t time_gettimeofday_us(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint64_t)tv.tv_sec * 1000000ULL + (uint64_t)tv.tv_usec;
+}
+
+static uint8_t *memsearch(uint8_t *haystack, uint32_t hlen, uint8_t *needle, uint32_t nlen)
+{
+ while (hlen-- >= nlen) {
+ if (!memcmp(haystack, needle, nlen)) {
+ return haystack;
+ }
+ haystack++;
+ }
+ return NULL;
+}
+
+static int32_t xr_raw_write(int type, uint8_t *data, uint32_t len)
+{
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 13] = {'B', 'R', 'O', 'M', 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t *psend = data;
+ uint32_t lsend = len;
+ cmd_header_t *hdr = (cmd_header_t *)buffer;;
+ cmd_ack_t *ack = (cmd_ack_t *)buffer;
+
+ if (type != DATA_RAW) {
+ psend = buffer;
+ lsend = MB_CMD_HEADER_SIZE + len;
+ memcpy(buffer + MB_CMD_HEADER_SIZE, data, len);
+ hdr->payload_len = len;
+#if ENABLE_DCS
+ hdr->flags = CMD_HFLAG_CHECK;
+#endif
+ hdr->checksum = ~CheckSum16(buffer, MB_CMD_HEADER_SIZE + len);
+ hdr->payload_len = SWAP32(hdr->payload_len);
+ hdr->checksum = SWAP16(hdr->checksum);
+ switch (type) {
+ case CMD_WRITESEQ:
+ {
+ cmd_seq_wr_t *cmd = (cmd_seq_wr_t *)buffer;
+ cmd->addr = SWAP32(cmd->addr);
+ cmd->dlen = SWAP32(cmd->dlen);
+ cmd->dcs = SWAP16(cmd->dcs);
+ }
+ break;
+ case CMD_SETBAUD:
+ {
+ cmd_sys_setuart_t *cmd = (cmd_sys_setuart_t*)buffer;
+ cmd->lcr = SWAP32(cmd->lcr);
+ }
+ break;
+ case CMD_SETPC:
+ {
+ cmd_sys_t *cmd = (cmd_sys_t*)buffer;
+ cmd->val = SWAP32(cmd->val);
+ }
+ break;
+ default:
+ XR_ERR("%s: Unsupport type %d", __func__, type);
+ return -1;
+ }
+ }
+
+ ssize_t ret_w, ret_r;
+ uint64_t t0, t1, t2, t3;
+
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ t0 = time_gettimeofday_us();
+ ret_w = userial_write(psend, lsend);
+ t1 = time_gettimeofday_us();
+
+ memset(buffer, 0, MB_CMD_HEADER_SIZE + 1);
+
+ t2 = time_gettimeofday_us();
+ ret_r = userial_read(buffer, MB_CMD_HEADER_SIZE, 100000);
+ t3 = time_gettimeofday_us();
+
+ XR_DBG("%s, type: %d, write len: %5d, ret: %5d, time: %6lluus, read len: %2d, ret: %2d, %6lluus",
+ __func__, type, lsend, ret_w, t1 - t0, MB_CMD_HEADER_SIZE, ret_r, t3 - t2);
+
+ uint8_t *p = (uint8_t *)memsearch(buffer, MB_CMD_HEADER_SIZE, (uint8_t *)"BROM", 4);
+ if (p != buffer) {
+ if (p == NULL) {
+ XR_ERR("%s: invalid response", __func__);
+ return -1;
+ }
+ uint32_t nowread = buffer + MB_CMD_HEADER_SIZE - p;
+ uint32_t needread = p - buffer;
+ XR_DBG("%s: Index error, re-find header magic", __func__);
+ memcpy(buffer, p, nowread);
+ memset(buffer + nowread, 0x0, needread);
+ userial_read(buffer + nowread, needread, 100000);
+ }
+
+ /* check response */
+ if (ack->h.flags & CMD_HFLAG_ERROR) {
+ userial_read(buffer + MB_CMD_HEADER_SIZE, 1, 100000);
+ XR_ERR("%s: resp error flag, type %d", __func__, ack->err);
+ return -ack->err;
+ }
+
+ if (ack->h.flags & CMD_HFLAG_ACK) {
+ /* convert network byte order to host byte order */
+ ack->h.payload_len = SWAP32(ack->h.payload_len);
+ ack->h.checksum = SWAP16(ack->h.checksum);
+ if (ack->h.payload_len != 0) {
+ XR_ERR("%s: data payload len %d != 0", __func__, ack->h.payload_len);
+ return -1;
+ }
+ }
+
+ if (ack->h.flags & CMD_HFLAG_CHECK) {
+ if (CheckSum16(buffer, MB_CMD_HEADER_SIZE) != 0xffff) {
+ XR_ERR("%s: write data response 0 checksum error", __func__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int32_t cmd_sync_uart(void)
+{
+ uint8_t sync = 0x55;
+ uint8_t ack[3] = {0};
+ ssize_t ret = -1;
+ uint32_t cnt = 0;
+
+ do {
+ XR_DBG("uart sync count:%d.", cnt);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+ userial_write(&sync, 1);
+ ret = userial_read(ack, 2, 2000);
+ if (ret == 2 && ((ack[0] == 'O' && ack[1] == 'K') || (ack[0] == 'K' && ack[1] == 'O'))) {
+ XR_DBG("Receive %s, uart Sync done.", ack);
+ return 0;
+ }
+ } while (cnt++ < 50);
+
+ XR_DBG("uart sync fail.");
+ return -1;
+}
+
+static int32_t cmd_sync_baud(uint32_t lcr)
+{
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 5];
+ cmd_sys_setuart_t *cmd = (cmd_sys_setuart_t*)buffer;
+
+ cmd->cmdid = CMD_ID_SETUART;
+ cmd->lcr = lcr;
+
+ uint8_t cnt = 0;
+ int ret = -1;
+
+ do {
+ XR_DBG("%s count:%d.", __func__, cnt);
+ ret = xr_raw_write(CMD_SETBAUD, buffer + MB_CMD_HEADER_SIZE, 5);
+ if (ret == 0) {
+ set_speed(vnd_userial.fd, vnd_userial.ti, lcr & 0xffffff);
+ return cmd_sync_uart();
+ }
+ } while (cnt++ < 3);
+
+ XR_DBG("cmd_sync_baud fail.");
+ return -1;
+}
+
+static int32_t cmd_write_seq(uint32_t addr, uint32_t len, uint8_t *data)
+{
+ int ret = -1;
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 13];
+ cmd_seq_wr_t *cmd = (cmd_seq_wr_t *)buffer;
+
+ cmd->cmdid = CMD_ID_SEQWR;
+ cmd->addr = addr;
+ cmd->dlen = len;
+#if ENABLE_DCS
+ cmd->dcs = ~CheckSum16(data, len);
+#endif
+
+ ret = xr_raw_write(CMD_WRITESEQ, buffer + MB_CMD_HEADER_SIZE, 11);
+ if (ret == 0) {
+ return xr_raw_write(DATA_RAW, data, len);
+ }
+ return ret;
+}
+
+static int32_t cmd_set_pc(uint32_t pc)
+{
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 5];
+ cmd_sys_t *cmd = (cmd_sys_t*)buffer;
+
+ cmd->cmdid = CMD_ID_SETPC;
+ cmd->val = pc;
+ XR_DBG("set pc %x, val %x", pc, cmd->val);
+
+ return xr_raw_write(CMD_SETPC, buffer + MB_CMD_HEADER_SIZE, 5);
+}
+
+static void userial_set_hw_fctrl(uint8_t hw_fctrl)
+{
+ if (vnd_userial.fd == -1) {
+ XR_ERR("vnd_userial.fd is -1");
+ return;
+ }
+
+ if (hw_fctrl) {
+ XR_DBG("Set HW FlowControl On");
+ vnd_userial.ti->c_cflag |= CRTSCTS;
+ } else {
+ XR_DBG("Set HW FlowControl Off");
+ vnd_userial.ti->c_cflag &= ~CRTSCTS;
+ }
+ tcsetattr(vnd_userial.fd, TCSANOW, vnd_userial.ti);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+}
+
+static uint32_t userial_read(uint8_t *buffer, uint32_t len, uint32_t timeout)
+{
+ fd_set set;
+ struct timeval tv;
+ int rv;
+
+ FD_ZERO(&set); /* clear the set */
+ FD_SET(vnd_userial.fd, &set); /* add our file descriptor to the set */
+
+ /* there was data to read */
+ ssize_t r;
+ uint8_t *pos = (uint8_t*)buffer;
+
+ while (len > 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout;
+
+ rv = select(vnd_userial.fd + 1, &set, NULL, NULL, &tv);
+ if(rv == -1) {
+ XR_ERR("select error"); /* an error accured */
+ break;
+ } else if(rv == 0) {
+ XR_ERR("read timeout"); /* a timeout occured */
+ break;
+ }
+
+ r = read(vnd_userial.fd, pos, len);
+ if (r < 1)
+ break;
+
+ len -= r;
+ pos += r;
+ }
+
+ return pos - buffer;
+}
+
+static uint32_t userial_write(const uint8_t *buffer, uint32_t len)
+{
+ ssize_t r;
+ uint8_t *pos = (uint8_t*)buffer;
+
+ while (len > 0) {
+ r = write(vnd_userial.fd, pos, len);
+ if (r < 1)
+ break;
+
+ len -= r;
+ pos += r;
+ }
+
+ return pos - buffer;
+}
+
+static int32_t load_btfirmware(void)
+{
+ FILE *fwfile_fd = NULL;
+ uint32_t len;
+ uint8_t *data = NULL;
+ uint32_t addr = BT_FW_LOAD_ADDR;
+ uint32_t section = SZ_16K;
+
+ fwfile_fd = fopen(BT_FW_PATH_NAME, "rb");
+ XR_DBG("BT firmware: %s", BT_FW_PATH_NAME);
+ if(!fwfile_fd) {
+ XR_ERR("Unable to open BT firmware %s", BT_FW_PATH_NAME);
+ return -1;
+ }
+
+ data = (uint8_t*)malloc(section);
+ if (data == NULL) {
+ XR_DBG("failed to alloc %d byte memory.", section);
+ fclose(fwfile_fd);
+ return -1;
+ }
+
+ XR_DBG("load bt firmware starting.");
+ while ((len = fread(data, 1, section, fwfile_fd)) > 0) {
+ cmd_write_seq(addr, len, data);
+ addr += len;
+ }
+
+ free(data);
+ fclose(fwfile_fd);
+ XR_DBG("load firmware done.");
+
+ XR_DBG("Firmware run from address 0x%08X", BT_FW_JUMP_ADDR);
+ cmd_set_pc(BT_FW_JUMP_ADDR);
+
+ if (CHIP_NAME == AW1732) {
+ XR_DBG("second time sync starting....");
+ if (cmd_sync_uart() < 0)
+ return -1;
+ cmd_set_pc(BT_FW_JUMP_ADDR);
+ }
+ return addr;
+}
+
+static int hci_cmd_handle(const uint8_t *cmd, uint32_t cmd_len, uint32_t event_len)
+{
+ uint8_t buffer[256];
+
+ XR_DBG("send hci command");
+ userial_write(cmd, cmd_len);
+ XR_DUMP(cmd, cmd_len);
+
+ if (read_hci_event(vnd_userial.fd, buffer, event_len) != event_len) {
+ XR_ERR("Event read error");
+ return -1;
+ }
+ XR_DBG("Received event");
+ XR_DUMP(buffer, event_len);
+ return 0;
+}
+
+int xr_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ vnd_userial.fd = fd;
+ vnd_userial.ti = ti;
+
+ XR_DBG("uart sync starting....");
+ if (cmd_sync_uart() < 0)
+ goto END;
+ XR_DBG("set bandrate to %d.", u->speed);
+ if (cmd_sync_baud(((u->speed) | (3<<24))) < 0)
+ goto END;
+ if (load_btfirmware() < 0)
+ goto END;
+ XR_DBG("bt firmware is running....");
+
+ XR_DBG("set baudrate to %d", u->init_speed);
+ set_speed(vnd_userial.fd, vnd_userial.ti, u->init_speed);
+ userial_set_hw_fctrl(1);
+ usleep(50000);
+
+ XR_DBG("process hci reset...");
+ if (hci_cmd_handle(hci_reset, sizeof(hci_reset), 7) < 0)
+ goto END;
+
+ XR_DBG("process hci update baud...");
+ if (hci_cmd_handle(hci_update_baud_rate, sizeof(hci_update_baud_rate), 7) < 0)
+ goto END;
+
+ usleep(100000);
+
+ return 0;
+
+END:
+ XR_DBG("device fd = %d close", fd);
+ close(vnd_userial.fd);
+ vnd_userial.fd = -1;
+ vnd_userial.ti = NULL;
+
+ return -1;
+}
+
+int xr_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ XR_DBG("Done setting line discpline");
+ return 0;
+}
+
diff --git a/external/cache/sources/hcitools/hciconfig.c b/external/cache/sources/hcitools/hciconfig.c
new file mode 100644
index 0000000..ec83139
--- /dev/null
+++ b/external/cache/sources/hcitools/hciconfig.c
@@ -0,0 +1,2052 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky
+ * Copyright (C) 2002-2010 Marcel Holtmann
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include