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 +#include +#include +#include +#include + +#include +#include +#include + +#include "textfile.h" +#include "csr.h" + +static struct hci_dev_info di; +static int all; + +static void print_dev_hdr(struct hci_dev_info *di); +static void print_dev_info(int ctl, struct hci_dev_info *di); + +static void print_dev_list(int ctl, int flags) +{ + struct hci_dev_list_req *dl; + struct hci_dev_req *dr; + int i; + + if (!(dl = malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + + sizeof(uint16_t)))) { + perror("Can't allocate memory"); + exit(1); + } + dl->dev_num = HCI_MAX_DEV; + dr = dl->dev_req; + + if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) { + perror("Can't get device list"); + if(dl) { + free(dl); + dl = NULL; + } + exit(1); + } + + for (i = 0; i< dl->dev_num; i++) { + di.dev_id = (dr+i)->dev_id; + if (ioctl(ctl, HCIGETDEVINFO, (void *) &di) < 0) + continue; + if (hci_test_bit(HCI_RAW, &di.flags) && + !bacmp(&di.bdaddr, BDADDR_ANY)) { + int dd = hci_open_dev(di.dev_id); + hci_read_bd_addr(dd, &di.bdaddr, 1000); + hci_close_dev(dd); + } + print_dev_info(ctl, &di); + } + if(dl) { + free(dl); + dl = NULL; + } +} + +static void print_pkt_type(struct hci_dev_info *di) +{ + char *str; + str = hci_ptypetostr(di->pkt_type); + printf("\tPacket type: %s\n", str); + bt_free(str); +} + +static void print_link_policy(struct hci_dev_info *di) +{ + printf("\tLink policy: %s\n", hci_lptostr(di->link_policy)); +} + +static void print_link_mode(struct hci_dev_info *di) +{ + char *str; + str = hci_lmtostr(di->link_mode); + printf("\tLink mode: %s\n", str); + bt_free(str); +} + +static void print_dev_features(struct hci_dev_info *di, int format) +{ + printf("\tFeatures: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", + di->features[0], di->features[1], di->features[2], + di->features[3], di->features[4], di->features[5], + di->features[6], di->features[7]); + + if (format) { + char *tmp = lmp_featurestostr(di->features, "\t\t", 63); + printf("%s\n", tmp); + bt_free(tmp); + } +} + +static void print_le_states(uint64_t states) +{ + int i; + const char *le_states[] = { + "Non-connectable Advertising State" , + "Scannable Advertising State", + "Connectable Advertising State", + "Directed Advertising State", + "Passive Scanning State", + "Active Scanning State", + "Initiating State/Connection State in Master Role", + "Connection State in the Slave Role", + "Non-connectable Advertising State and Passive Scanning State combination", + "Scannable Advertising State and Passive Scanning State combination", + "Connectable Advertising State and Passive Scanning State combination", + "Directed Advertising State and Passive Scanning State combination", + "Non-connectable Advertising State and Active Scanning State combination", + "Scannable Advertising State and Active Scanning State combination", + "Connectable Advertising State and Active Scanning State combination", + "Directed Advertising State and Active Scanning State combination", + "Non-connectable Advertising State and Initiating State combination", + "Scannable Advertising State and Initiating State combination", + "Non-connectable Advertising State and Master Role combination", + "Scannable Advertising State and Master Role combination", + "Non-connectable Advertising State and Slave Role combination", + "Scannable Advertising State and Slave Role combination", + "Passive Scanning State and Initiating State combination", + "Active Scanning State and Initiating State combination", + "Passive Scanning State and Master Role combination", + "Active Scanning State and Master Role combination", + "Passive Scanning State and Slave Role combination", + "Active Scanning State and Slave Role combination", + "Initiating State and Master Role combination/Master Role and Master Role combination", + NULL + }; + + printf("Supported link layer states:\n"); + for (i = 0; le_states[i]; i++) { + const char *status; + + status = states & (1 << i) ? "YES" : "NO "; + printf("\t%s %s\n", status, le_states[i]); + } +} + +static void cmd_rstat(int ctl, int hdev, char *opt) +{ + /* Reset HCI device stat counters */ + if (ioctl(ctl, HCIDEVRESTAT, hdev) < 0) { + fprintf(stderr, "Can't reset stats counters hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_scan(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr; + + dr.dev_id = hdev; + dr.dev_opt = SCAN_DISABLED; + if (!strcmp(opt, "iscan")) + dr.dev_opt = SCAN_INQUIRY; + else if (!strcmp(opt, "pscan")) + dr.dev_opt = SCAN_PAGE; + else if (!strcmp(opt, "piscan")) + dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY; + + if (ioctl(ctl, HCISETSCAN, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set scan mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_le_addr(int ctl, int hdev, char *opt) +{ + struct hci_request rq; + le_set_random_address_cp cp; + uint8_t status; + int dd, err, ret; + + if (!opt) + return; + + if (hdev < 0) + hdev = hci_get_route(NULL); + + dd = hci_open_dev(hdev); + if (dd < 0) { + err = -errno; + fprintf(stderr, "Could not open device: %s(%d)\n", + strerror(-err), -err); + exit(1); + } + + memset(&cp, 0, sizeof(cp)); + + str2ba(opt, &cp.bdaddr); + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_LE_CTL; + rq.ocf = OCF_LE_SET_RANDOM_ADDRESS; + rq.cparam = &cp; + rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE; + rq.rparam = &status; + rq.rlen = 1; + + ret = hci_send_req(dd, &rq, 1000); + if (status || ret < 0) { + err = -errno; + fprintf(stderr, "Can't set random address for hci%d: " + "%s (%d)\n", hdev, strerror(-err), -err); + } + + hci_close_dev(dd); +} + +static void cmd_le_adv(int ctl, int hdev, char *opt) +{ + struct hci_request rq; + le_set_advertise_enable_cp advertise_cp; + le_set_advertising_parameters_cp adv_params_cp; + uint8_t status; + int dd, ret; + + if (hdev < 0) + hdev = hci_get_route(NULL); + + dd = hci_open_dev(hdev); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + memset(&adv_params_cp, 0, sizeof(adv_params_cp)); + adv_params_cp.min_interval = htobs(0x0800); + adv_params_cp.max_interval = htobs(0x0800); + if (opt) + adv_params_cp.advtype = atoi(opt); + adv_params_cp.chan_map = 7; + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_LE_CTL; + rq.ocf = OCF_LE_SET_ADVERTISING_PARAMETERS; + rq.cparam = &adv_params_cp; + rq.clen = LE_SET_ADVERTISING_PARAMETERS_CP_SIZE; + rq.rparam = &status; + rq.rlen = 1; + + ret = hci_send_req(dd, &rq, 1000); + if (ret < 0) + goto done; + + memset(&advertise_cp, 0, sizeof(advertise_cp)); + advertise_cp.enable = 0x01; + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_LE_CTL; + rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE; + rq.cparam = &advertise_cp; + rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE; + rq.rparam = &status; + rq.rlen = 1; + + ret = hci_send_req(dd, &rq, 1000); + +done: + hci_close_dev(dd); + + if (ret < 0) { + fprintf(stderr, "Can't set advertise mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (status) { + fprintf(stderr, + "LE set advertise enable on hci%d returned status %d\n", + hdev, status); + exit(1); + } +} + +static void cmd_no_le_adv(int ctl, int hdev, char *opt) +{ + struct hci_request rq; + le_set_advertise_enable_cp advertise_cp; + uint8_t status; + int dd, ret; + + if (hdev < 0) + hdev = hci_get_route(NULL); + + dd = hci_open_dev(hdev); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + memset(&advertise_cp, 0, sizeof(advertise_cp)); + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_LE_CTL; + rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE; + rq.cparam = &advertise_cp; + rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE; + rq.rparam = &status; + rq.rlen = 1; + + ret = hci_send_req(dd, &rq, 1000); + + hci_close_dev(dd); + + if (ret < 0) { + fprintf(stderr, "Can't set advertise mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (status) { + fprintf(stderr, "LE set advertise enable on hci%d returned status %d\n", + hdev, status); + exit(1); + } +} + +static void cmd_le_states(int ctl, int hdev, char *opt) +{ + le_read_supported_states_rp rp; + struct hci_request rq; + int err, dd; + + if (hdev < 0) + hdev = hci_get_route(NULL); + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + memset(&rp, 0, sizeof(rp)); + memset(&rq, 0, sizeof(rq)); + + rq.ogf = OGF_LE_CTL; + rq.ocf = OCF_LE_READ_SUPPORTED_STATES; + rq.rparam = &rp; + rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE; + + err = hci_send_req(dd, &rq, 1000); + + hci_close_dev(dd); + + if (err < 0) { + fprintf(stderr, "Can't read LE supported states on hci%d:" + " %s(%d)\n", hdev, strerror(errno), errno); + exit(1); + } + + if (rp.status) { + fprintf(stderr, "Read LE supported states on hci%d" + " returned status %d\n", hdev, rp.status); + exit(1); + } + + print_le_states(rp.states); +} + +static void cmd_iac(int ctl, int hdev, char *opt) +{ + int s = hci_open_dev(hdev); + + if (s < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + if (opt) { + int l = strtoul(opt, 0, 16); + uint8_t lap[3]; + if (!strcasecmp(opt, "giac")) { + l = 0x9e8b33; + } else if (!strcasecmp(opt, "liac")) { + l = 0x9e8b00; + } else if (l < 0x9e8b00 || l > 0x9e8b3f) { + printf("Invalid access code 0x%x\n", l); + exit(1); + } + lap[0] = (l & 0xff); + lap[1] = (l >> 8) & 0xff; + lap[2] = (l >> 16) & 0xff; + if (hci_write_current_iac_lap(s, 1, lap, 1000) < 0) { + printf("Failed to set IAC on hci%d: %s\n", hdev, strerror(errno)); + exit(1); + } + } else { + uint8_t lap[3 * MAX_IAC_LAP]; + int i, j; + uint8_t n; + if (hci_read_current_iac_lap(s, &n, lap, 1000) < 0) { + printf("Failed to read IAC from hci%d: %s\n", hdev, strerror(errno)); + exit(1); + } + print_dev_hdr(&di); + printf("\tIAC: "); + for (i = 0; i < n; i++) { + printf("0x"); + for (j = 3; j--; ) + printf("%02x", lap[j + 3 * i]); + if (i < n - 1) + printf(", "); + } + printf("\n"); + } + close(s); +} + +static void cmd_auth(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr; + + dr.dev_id = hdev; + if (!strcmp(opt, "auth")) + dr.dev_opt = AUTH_ENABLED; + else + dr.dev_opt = AUTH_DISABLED; + + if (ioctl(ctl, HCISETAUTH, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set auth on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_encrypt(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr; + + dr.dev_id = hdev; + if (!strcmp(opt, "encrypt")) + dr.dev_opt = ENCRYPT_P2P; + else + dr.dev_opt = ENCRYPT_DISABLED; + + if (ioctl(ctl, HCISETENCRYPT, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set encrypt on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_up(int ctl, int hdev, char *opt) +{ + /* Start HCI device */ + if (ioctl(ctl, HCIDEVUP, hdev) < 0) { + if (errno == EALREADY) + return; + fprintf(stderr, "Can't init device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_down(int ctl, int hdev, char *opt) +{ + /* Stop HCI device */ + if (ioctl(ctl, HCIDEVDOWN, hdev) < 0) { + fprintf(stderr, "Can't down device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_reset(int ctl, int hdev, char *opt) +{ + /* Reset HCI device */ +#if 0 + if (ioctl(ctl, HCIDEVRESET, hdev) < 0 ){ + fprintf(stderr, "Reset failed for device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +#endif + cmd_down(ctl, hdev, "down"); + cmd_up(ctl, hdev, "up"); +} + +static void cmd_ptype(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr; + + dr.dev_id = hdev; + + if (hci_strtoptype(opt, &dr.dev_opt)) { + if (ioctl(ctl, HCISETPTYPE, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set pkttype on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + print_dev_hdr(&di); + print_pkt_type(&di); + } +} + +static void cmd_lp(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr; + + dr.dev_id = hdev; + + if (hci_strtolp(opt, &dr.dev_opt)) { + if (ioctl(ctl, HCISETLINKPOL, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set link policy on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + print_dev_hdr(&di); + print_link_policy(&di); + } +} + +static void cmd_lm(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr; + + dr.dev_id = hdev; + + if (hci_strtolm(opt, &dr.dev_opt)) { + if (ioctl(ctl, HCISETLINKMODE, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set default link mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + print_dev_hdr(&di); + print_link_mode(&di); + } +} + +static void cmd_aclmtu(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr = { .dev_id = hdev }; + uint16_t mtu, mpkt; + + if (!opt) + return; + + if (sscanf(opt, "%4hu:%4hu", &mtu, &mpkt) != 2) + return; + + dr.dev_opt = htobl(htobs(mpkt) | (htobs(mtu) << 16)); + + if (ioctl(ctl, HCISETACLMTU, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set ACL mtu on hci%d: %s(%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_scomtu(int ctl, int hdev, char *opt) +{ + struct hci_dev_req dr = { .dev_id = hdev }; + uint16_t mtu, mpkt; + + if (!opt) + return; + + if (sscanf(opt, "%4hu:%4hu", &mtu, &mpkt) != 2) + return; + + dr.dev_opt = htobl(htobs(mpkt) | (htobs(mtu) << 16)); + + if (ioctl(ctl, HCISETSCOMTU, (unsigned long) &dr) < 0) { + fprintf(stderr, "Can't set SCO mtu on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } +} + +static void cmd_features(int ctl, int hdev, char *opt) +{ + uint8_t features[8], max_page = 0; + char *tmp; + int i, dd; + + if (!(di.features[7] & LMP_EXT_FEAT)) { + print_dev_hdr(&di); + print_dev_features(&di, 1); + return; + } + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (hci_read_local_ext_features(dd, 0, &max_page, features, 1000) < 0) { + fprintf(stderr, "Can't read extended features hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tFeatures%s: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", + (max_page > 0) ? " page 0" : "", + features[0], features[1], features[2], features[3], + features[4], features[5], features[6], features[7]); + + tmp = lmp_featurestostr(di.features, "\t\t", 63); + printf("%s\n", tmp); + bt_free(tmp); + + for (i = 1; i <= max_page; i++) { + if (hci_read_local_ext_features(dd, i, NULL, + features, 1000) < 0) + continue; + + printf("\tFeatures page %d: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", i, + features[0], features[1], features[2], features[3], + features[4], features[5], features[6], features[7]); + } + + hci_close_dev(dd); +} + +static void cmd_name(int ctl, int hdev, char *opt) +{ + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (opt) { + if (hci_write_local_name(dd, opt, 2000) < 0) { + fprintf(stderr, "Can't change local name on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + char name[249]; + int i; + + if (hci_read_local_name(dd, sizeof(name), name, 1000) < 0) { + fprintf(stderr, "Can't read local name on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + for (i = 0; i < 248 && name[i]; i++) { + if ((unsigned char) name[i] < 32 || name[i] == 127) + name[i] = '.'; + } + + name[248] = '\0'; + + print_dev_hdr(&di); + printf("\tName: '%s'\n", name); + } + + hci_close_dev(dd); +} + +/* + * see http://www.bluetooth.org/assigned-numbers/baseband.htm --- all + * strings are reproduced verbatim + */ +static char *get_minor_device_name(int major, int minor) +{ + switch (major) { + case 0: /* misc */ + return ""; + case 1: /* computer */ + switch (minor) { + case 0: + return "Uncategorized"; + case 1: + return "Desktop workstation"; + case 2: + return "Server"; + case 3: + return "Laptop"; + case 4: + return "Handheld"; + case 5: + return "Palm"; + case 6: + return "Wearable"; + } + break; + case 2: /* phone */ + switch (minor) { + case 0: + return "Uncategorized"; + case 1: + return "Cellular"; + case 2: + return "Cordless"; + case 3: + return "Smart phone"; + case 4: + return "Wired modem or voice gateway"; + case 5: + return "Common ISDN Access"; + case 6: + return "Sim Card Reader"; + } + break; + case 3: /* lan access */ + if (minor == 0) + return "Uncategorized"; + switch (minor / 8) { + case 0: + return "Fully available"; + case 1: + return "1-17% utilized"; + case 2: + return "17-33% utilized"; + case 3: + return "33-50% utilized"; + case 4: + return "50-67% utilized"; + case 5: + return "67-83% utilized"; + case 6: + return "83-99% utilized"; + case 7: + return "No service available"; + } + break; + case 4: /* audio/video */ + switch (minor) { + case 0: + return "Uncategorized"; + case 1: + return "Device conforms to the Headset profile"; + case 2: + return "Hands-free"; + /* 3 is reserved */ + case 4: + return "Microphone"; + case 5: + return "Loudspeaker"; + case 6: + return "Headphones"; + case 7: + return "Portable Audio"; + case 8: + return "Car Audio"; + case 9: + return "Set-top box"; + case 10: + return "HiFi Audio Device"; + case 11: + return "VCR"; + case 12: + return "Video Camera"; + case 13: + return "Camcorder"; + case 14: + return "Video Monitor"; + case 15: + return "Video Display and Loudspeaker"; + case 16: + return "Video Conferencing"; + /* 17 is reserved */ + case 18: + return "Gaming/Toy"; + } + break; + case 5: /* peripheral */ { + static char cls_str[48]; + + cls_str[0] = '\0'; + + switch (minor & 48) { + case 16: + strncpy(cls_str, "Keyboard", sizeof(cls_str)); + break; + case 32: + strncpy(cls_str, "Pointing device", sizeof(cls_str)); + break; + case 48: + strncpy(cls_str, "Combo keyboard/pointing device", sizeof(cls_str)); + break; + } + if ((minor & 15) && (strlen(cls_str) > 0)) + strcat(cls_str, "/"); + + switch (minor & 15) { + case 0: + break; + case 1: + strncat(cls_str, "Joystick", sizeof(cls_str) - strlen(cls_str)); + break; + case 2: + strncat(cls_str, "Gamepad", sizeof(cls_str) - strlen(cls_str)); + break; + case 3: + strncat(cls_str, "Remote control", sizeof(cls_str) - strlen(cls_str)); + break; + case 4: + strncat(cls_str, "Sensing device", sizeof(cls_str) - strlen(cls_str)); + break; + case 5: + strncat(cls_str, "Digitizer tablet", sizeof(cls_str) - strlen(cls_str)); + break; + case 6: + strncat(cls_str, "Card reader", sizeof(cls_str) - strlen(cls_str)); + break; + default: + strncat(cls_str, "(reserved)", sizeof(cls_str) - strlen(cls_str)); + break; + } + if (strlen(cls_str) > 0) + return cls_str; + } + case 6: /* imaging */ + if (minor & 4) + return "Display"; + if (minor & 8) + return "Camera"; + if (minor & 16) + return "Scanner"; + if (minor & 32) + return "Printer"; + break; + case 7: /* wearable */ + switch (minor) { + case 1: + return "Wrist Watch"; + case 2: + return "Pager"; + case 3: + return "Jacket"; + case 4: + return "Helmet"; + case 5: + return "Glasses"; + } + break; + case 8: /* toy */ + switch (minor) { + case 1: + return "Robot"; + case 2: + return "Vehicle"; + case 3: + return "Doll / Action Figure"; + case 4: + return "Controller"; + case 5: + return "Game"; + } + break; + case 63: /* uncategorised */ + return ""; + } + return "Unknown (reserved) minor device class"; +} + +static void cmd_class(int ctl, int hdev, char *opt) +{ + static const char *services[] = { "Positioning", + "Networking", + "Rendering", + "Capturing", + "Object Transfer", + "Audio", + "Telephony", + "Information" }; + static const char *major_devices[] = { "Miscellaneous", + "Computer", + "Phone", + "LAN Access", + "Audio/Video", + "Peripheral", + "Imaging", + "Uncategorized" }; + int s = hci_open_dev(hdev); + + if (s < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + if (opt) { + uint32_t cod = strtoul(opt, NULL, 16); + if (hci_write_class_of_dev(s, cod, 2000) < 0) { + fprintf(stderr, "Can't write local class of device on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint8_t cls[3]; + if (hci_read_class_of_dev(s, cls, 1000) < 0) { + fprintf(stderr, "Can't read class of device on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + print_dev_hdr(&di); + printf("\tClass: 0x%02x%02x%02x\n", cls[2], cls[1], cls[0]); + printf("\tService Classes: "); + if (cls[2]) { + unsigned int i; + int first = 1; + for (i = 0; i < (sizeof(services) / sizeof(*services)); i++) + if (cls[2] & (1 << i)) { + if (!first) + printf(", "); + printf("%s", services[i]); + first = 0; + } + } else + printf("Unspecified"); + printf("\n\tDevice Class: "); + if ((cls[1] & 0x1f) >= sizeof(major_devices) / sizeof(*major_devices)) + printf("Invalid Device Class!\n"); + else + printf("%s, %s\n", major_devices[cls[1] & 0x1f], + get_minor_device_name(cls[1] & 0x1f, cls[0] >> 2)); + } +} + +static void cmd_voice(int ctl, int hdev, char *opt) +{ + static char *icf[] = { "Linear", + "u-Law", + "A-Law", + "Reserved" }; + + static char *idf[] = { "1's complement", + "2's complement", + "Sign-Magnitude", + "Reserved" }; + + static char *iss[] = { "8 bit", + "16 bit" }; + + static char *acf[] = { "CVSD", + "u-Law", + "A-Law", + "Reserved" }; + + int s = hci_open_dev(hdev); + + if (s < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + if (opt) { + uint16_t vs = htobs(strtoul(opt, NULL, 16)); + if (hci_write_voice_setting(s, vs, 2000) < 0) { + fprintf(stderr, "Can't write voice setting on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint16_t vs; + uint8_t ic; + if (hci_read_voice_setting(s, &vs, 1000) < 0) { + fprintf(stderr, "Can't read voice setting on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + vs = htobs(vs); + ic = (vs & 0x0300) >> 8; + print_dev_hdr(&di); + printf("\tVoice setting: 0x%04x%s\n", vs, + ((vs & 0x03fc) == 0x0060) ? " (Default Condition)" : ""); + printf("\tInput Coding: %s\n", icf[ic]); + printf("\tInput Data Format: %s\n", idf[(vs & 0xc0) >> 6]); + + if (!ic) { + printf("\tInput Sample Size: %s\n", + iss[(vs & 0x20) >> 5]); + printf("\t# of bits padding at MSB: %d\n", + (vs & 0x1c) >> 2); + } + printf("\tAir Coding Format: %s\n", acf[vs & 0x03]); + } +} + +static void cmd_delkey(int ctl, int hdev, char *opt) +{ + bdaddr_t bdaddr; + uint8_t all; + int dd; + + if (!opt) + return; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (!strcasecmp(opt, "all")) { + bacpy(&bdaddr, BDADDR_ANY); + all = 1; + } else { + str2ba(opt, &bdaddr); + all = 0; + } + + if (hci_delete_stored_link_key(dd, &bdaddr, all, 1000) < 0) { + fprintf(stderr, "Can't delete stored link key on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + hci_close_dev(dd); +} + +static void cmd_oob_data(int ctl, int hdev, char *opt) +{ + uint8_t hash[16], randomizer[16]; + int i, dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (hci_read_local_oob_data(dd, hash, randomizer, 1000) < 0) { + fprintf(stderr, "Can't read local OOB data on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tOOB Hash: "); + for (i = 0; i < 16; i++) + printf(" %02x", hash[i]); + printf("\n\tRandomizer:"); + for (i = 0; i < 16; i++) + printf(" %02x", randomizer[i]); + printf("\n"); + + hci_close_dev(dd); +} + +static void cmd_commands(int ctl, int hdev, char *opt) +{ + uint8_t cmds[64]; + char *str; + int i, n, dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (hci_read_local_commands(dd, cmds, 1000) < 0) { + fprintf(stderr, "Can't read support commands on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + for (i = 0; i < 64; i++) { + if (!cmds[i]) + continue; + + printf("%s Octet %-2d = 0x%02x (Bit", + i ? "\t\t ": "\tCommands:", i, cmds[i]); + for (n = 0; n < 8; n++) + if (cmds[i] & (1 << n)) + printf(" %d", n); + printf(")\n"); + } + + str = hci_commandstostr(cmds, "\t", 71); + printf("%s\n", str); + bt_free(str); + + hci_close_dev(dd); +} + +static void cmd_version(int ctl, int hdev, char *opt) +{ + struct hci_version ver; + char *hciver, *lmpver; + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (hci_read_local_version(dd, &ver, 1000) < 0) { + fprintf(stderr, "Can't read version info hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + hciver = hci_vertostr(ver.hci_ver); + if (((di.type & 0x30) >> 4) == HCI_BREDR) + lmpver = lmp_vertostr(ver.lmp_ver); + else + lmpver = pal_vertostr(ver.lmp_ver); + + print_dev_hdr(&di); + printf("\tHCI Version: %s (0x%x) Revision: 0x%x\n" + "\t%s Version: %s (0x%x) Subversion: 0x%x\n" + "\tManufacturer: %s (%d)\n", + hciver ? hciver : "n/a", ver.hci_ver, ver.hci_rev, + (((di.type & 0x30) >> 4) == HCI_BREDR) ? "LMP" : "PAL", + lmpver ? lmpver : "n/a", ver.lmp_ver, ver.lmp_subver, + bt_compidtostr(ver.manufacturer), ver.manufacturer); + + if (hciver) + bt_free(hciver); + if (lmpver) + bt_free(lmpver); + + hci_close_dev(dd); +} + +static void cmd_inq_tpl(int ctl, int hdev, char *opt) +{ + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (opt) { + int8_t level = atoi(opt); + + if (hci_write_inquiry_transmit_power_level(dd, level, 2000) < 0) { + fprintf(stderr, "Can't set inquiry transmit power level on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + int8_t level; + + if (hci_read_inq_response_tx_power_level(dd, &level, 1000) < 0) { + fprintf(stderr, "Can't read inquiry transmit power level on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tInquiry transmit power level: %d\n", level); + } + + hci_close_dev(dd); +} + +static void cmd_inq_mode(int ctl, int hdev, char *opt) +{ + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (opt) { + uint8_t mode = atoi(opt); + + if (hci_write_inquiry_mode(dd, mode, 2000) < 0) { + fprintf(stderr, "Can't set inquiry mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint8_t mode; + + if (hci_read_inquiry_mode(dd, &mode, 1000) < 0) { + fprintf(stderr, "Can't read inquiry mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tInquiry mode: "); + switch (mode) { + case 0: + printf("Standard Inquiry\n"); + break; + case 1: + printf("Inquiry with RSSI\n"); + break; + case 2: + printf("Inquiry with RSSI or Extended Inquiry\n"); + break; + default: + printf("Unknown (0x%02x)\n", mode); + break; + } + } + + hci_close_dev(dd); +} + +static void cmd_inq_data(int ctl, int hdev, char *opt) +{ + int i, dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (opt) { + uint8_t fec = 0, data[HCI_MAX_EIR_LENGTH]; + char tmp[3]; + int i, size; + + memset(data, 0, sizeof(data)); + + memset(tmp, 0, sizeof(tmp)); + size = (strlen(opt) + 1) / 2; + if (size > HCI_MAX_EIR_LENGTH) + size = HCI_MAX_EIR_LENGTH; + + for (i = 0; i < size; i++) { + memcpy(tmp, opt + (i * 2), 2); + data[i] = strtol(tmp, NULL, 16); + } + + if (hci_write_ext_inquiry_response(dd, fec, data, 2000) < 0) { + fprintf(stderr, "Can't set extended inquiry response on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint8_t fec, data[HCI_MAX_EIR_LENGTH], len, type, *ptr; + char *str; + + if (hci_read_ext_inquiry_response(dd, &fec, data, 1000) < 0) { + fprintf(stderr, "Can't read extended inquiry response on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tFEC %s\n\t\t", fec ? "enabled" : "disabled"); + for (i = 0; i < HCI_MAX_EIR_LENGTH; i++) + printf("%02x%s%s", data[i], (i + 1) % 8 ? "" : " ", + (i + 1) % 16 ? " " : (i < 239 ? "\n\t\t" : "\n")); + + ptr = data; + while (*ptr) { + len = *ptr++; + type = *ptr++; + switch (type) { + case 0x01: + printf("\tFlags:"); + for (i = 0; i < len - 1; i++) + printf(" 0x%2.2x", *((uint8_t *) (ptr + i))); + printf("\n"); + break; + case 0x02: + case 0x03: + printf("\t%s service classes:", + type == 0x02 ? "Shortened" : "Complete"); + for (i = 0; i < (len - 1) / 2; i++) { + uint16_t val = bt_get_le16((ptr + (i * 2))); + printf(" 0x%4.4x", val); + } + printf("\n"); + break; + case 0x08: + case 0x09: + str = malloc(len); + if (str) { + snprintf(str, len, "%s", ptr); + for (i = 0; i < len - 1; i++) { + if ((unsigned char) str[i] < 32 || str[i] == 127) + str[i] = '.'; + } + printf("\t%s local name: \'%s\'\n", + type == 0x08 ? "Shortened" : "Complete", str); + free(str); + } + break; + case 0x0a: + printf("\tTX power level: %d\n", *((int8_t *) ptr)); + break; + case 0x10: + printf("\tDevice ID with %d bytes data\n", + len - 1); + break; + default: + printf("\tUnknown type 0x%02x with %d bytes data\n", + type, len - 1); + break; + } + + ptr += (len - 1); + } + + printf("\n"); + } + + hci_close_dev(dd); +} + +static void cmd_inq_type(int ctl, int hdev, char *opt) +{ + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (opt) { + uint8_t type = atoi(opt); + + if (hci_write_inquiry_scan_type(dd, type, 2000) < 0) { + fprintf(stderr, "Can't set inquiry scan type on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint8_t type; + + if (hci_read_inquiry_scan_type(dd, &type, 1000) < 0) { + fprintf(stderr, "Can't read inquiry scan type on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tInquiry scan type: %s\n", + type == 1 ? "Interlaced Inquiry Scan" : "Standard Inquiry Scan"); + } + + hci_close_dev(dd); +} + +static void cmd_inq_parms(int ctl, int hdev, char *opt) +{ + struct hci_request rq; + int s; + + if ((s = hci_open_dev(hdev)) < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + memset(&rq, 0, sizeof(rq)); + + if (opt) { + unsigned int window, interval; + write_inq_activity_cp cp; + + if (sscanf(opt,"%4u:%4u", &window, &interval) != 2) { + printf("Invalid argument format\n"); + exit(1); + } + + rq.ogf = OGF_HOST_CTL; + rq.ocf = OCF_WRITE_INQ_ACTIVITY; + rq.cparam = &cp; + rq.clen = WRITE_INQ_ACTIVITY_CP_SIZE; + + cp.window = htobs((uint16_t) window); + cp.interval = htobs((uint16_t) interval); + + if (window < 0x12 || window > 0x1000) + printf("Warning: inquiry window out of range!\n"); + + if (interval < 0x12 || interval > 0x1000) + printf("Warning: inquiry interval out of range!\n"); + + if (hci_send_req(s, &rq, 2000) < 0) { + fprintf(stderr, "Can't set inquiry parameters name on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint16_t window, interval; + read_inq_activity_rp rp; + + rq.ogf = OGF_HOST_CTL; + rq.ocf = OCF_READ_INQ_ACTIVITY; + rq.rparam = &rp; + rq.rlen = READ_INQ_ACTIVITY_RP_SIZE; + + if (hci_send_req(s, &rq, 1000) < 0) { + fprintf(stderr, "Can't read inquiry parameters on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + if (rp.status) { + printf("Read inquiry parameters on hci%d returned status %d\n", + hdev, rp.status); + exit(1); + } + print_dev_hdr(&di); + + window = btohs(rp.window); + interval = btohs(rp.interval); + printf("\tInquiry interval: %u slots (%.2f ms), window: %u slots (%.2f ms)\n", + interval, (float)interval * 0.625, window, (float)window * 0.625); + } +} + +static void cmd_page_parms(int ctl, int hdev, char *opt) +{ + struct hci_request rq; + int s; + + if ((s = hci_open_dev(hdev)) < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + memset(&rq, 0, sizeof(rq)); + + if (opt) { + unsigned int window, interval; + write_page_activity_cp cp; + + if (sscanf(opt,"%4u:%4u", &window, &interval) != 2) { + printf("Invalid argument format\n"); + exit(1); + } + + rq.ogf = OGF_HOST_CTL; + rq.ocf = OCF_WRITE_PAGE_ACTIVITY; + rq.cparam = &cp; + rq.clen = WRITE_PAGE_ACTIVITY_CP_SIZE; + + cp.window = htobs((uint16_t) window); + cp.interval = htobs((uint16_t) interval); + + if (window < 0x12 || window > 0x1000) + printf("Warning: page window out of range!\n"); + + if (interval < 0x12 || interval > 0x1000) + printf("Warning: page interval out of range!\n"); + + if (hci_send_req(s, &rq, 2000) < 0) { + fprintf(stderr, "Can't set page parameters name on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint16_t window, interval; + read_page_activity_rp rp; + + rq.ogf = OGF_HOST_CTL; + rq.ocf = OCF_READ_PAGE_ACTIVITY; + rq.rparam = &rp; + rq.rlen = READ_PAGE_ACTIVITY_RP_SIZE; + + if (hci_send_req(s, &rq, 1000) < 0) { + fprintf(stderr, "Can't read page parameters on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + if (rp.status) { + printf("Read page parameters on hci%d returned status %d\n", + hdev, rp.status); + exit(1); + } + print_dev_hdr(&di); + + window = btohs(rp.window); + interval = btohs(rp.interval); + printf("\tPage interval: %u slots (%.2f ms), " + "window: %u slots (%.2f ms)\n", + interval, (float)interval * 0.625, + window, (float)window * 0.625); + } +} + +static void cmd_page_to(int ctl, int hdev, char *opt) +{ + struct hci_request rq; + int s; + + if ((s = hci_open_dev(hdev)) < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + memset(&rq, 0, sizeof(rq)); + + if (opt) { + unsigned int timeout; + write_page_timeout_cp cp; + + if (sscanf(opt,"%5u", &timeout) != 1) { + printf("Invalid argument format\n"); + exit(1); + } + + rq.ogf = OGF_HOST_CTL; + rq.ocf = OCF_WRITE_PAGE_TIMEOUT; + rq.cparam = &cp; + rq.clen = WRITE_PAGE_TIMEOUT_CP_SIZE; + + cp.timeout = htobs((uint16_t) timeout); + + if (timeout < 0x01 || timeout > 0xFFFF) + printf("Warning: page timeout out of range!\n"); + + if (hci_send_req(s, &rq, 2000) < 0) { + fprintf(stderr, "Can't set page timeout on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint16_t timeout; + read_page_timeout_rp rp; + + rq.ogf = OGF_HOST_CTL; + rq.ocf = OCF_READ_PAGE_TIMEOUT; + rq.rparam = &rp; + rq.rlen = READ_PAGE_TIMEOUT_RP_SIZE; + + if (hci_send_req(s, &rq, 1000) < 0) { + fprintf(stderr, "Can't read page timeout on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + if (rp.status) { + printf("Read page timeout on hci%d returned status %d\n", + hdev, rp.status); + exit(1); + } + print_dev_hdr(&di); + + timeout = btohs(rp.timeout); + printf("\tPage timeout: %u slots (%.2f ms)\n", + timeout, (float)timeout * 0.625); + } +} + +static void cmd_afh_mode(int ctl, int hdev, char *opt) +{ + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (opt) { + uint8_t mode = atoi(opt); + + if (hci_write_afh_mode(dd, mode, 2000) < 0) { + fprintf(stderr, "Can't set AFH mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint8_t mode; + + if (hci_read_afh_mode(dd, &mode, 1000) < 0) { + fprintf(stderr, "Can't read AFH mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tAFH mode: %s\n", mode == 1 ? "Enabled" : "Disabled"); + } +} + +static void cmd_ssp_mode(int ctl, int hdev, char *opt) +{ + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (opt) { + uint8_t mode = atoi(opt); + + if (hci_write_simple_pairing_mode(dd, mode, 2000) < 0) { + fprintf(stderr, "Can't set Simple Pairing mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + } else { + uint8_t mode; + + if (hci_read_simple_pairing_mode(dd, &mode, 1000) < 0) { + fprintf(stderr, "Can't read Simple Pairing mode on hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + print_dev_hdr(&di); + printf("\tSimple Pairing mode: %s\n", + mode == 1 ? "Enabled" : "Disabled"); + } +} + +static void print_rev_ericsson(int dd) +{ + struct hci_request rq; + unsigned char buf[102]; + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_VENDOR_CMD; + rq.ocf = 0x000f; + rq.cparam = NULL; + rq.clen = 0; + rq.rparam = &buf; + rq.rlen = sizeof(buf); + + if (hci_send_req(dd, &rq, 1000) < 0) { + printf("\nCan't read revision info: %s (%d)\n", + strerror(errno), errno); + return; + } + + printf("\t%s\n", buf + 1); +} + +static void print_rev_csr(int dd, uint16_t rev) +{ + uint16_t buildid, chipver, chiprev, maxkeylen, mapsco; + + if (csr_read_varid_uint16(dd, 0, CSR_VARID_BUILDID, &buildid) < 0) { + printf("\t%s\n", csr_buildidtostr(rev)); + return; + } + + printf("\t%s\n", csr_buildidtostr(buildid)); + + if (!csr_read_varid_uint16(dd, 1, CSR_VARID_CHIPVER, &chipver)) { + if (csr_read_varid_uint16(dd, 2, CSR_VARID_CHIPREV, &chiprev) < 0) + chiprev = 0; + printf("\tChip version: %s\n", csr_chipvertostr(chipver, chiprev)); + } + + if (!csr_read_varid_uint16(dd, 3, CSR_VARID_MAX_CRYPT_KEY_LENGTH, &maxkeylen)) + printf("\tMax key size: %d bit\n", maxkeylen * 8); + + if (!csr_read_pskey_uint16(dd, 4, CSR_PSKEY_HOSTIO_MAP_SCO_PCM, 0x0000, &mapsco)) + printf("\tSCO mapping: %s\n", mapsco ? "PCM" : "HCI"); +} + +static void print_rev_digianswer(int dd) +{ + struct hci_request rq; + unsigned char req[] = { 0x07 }; + unsigned char buf[102]; + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_VENDOR_CMD; + rq.ocf = 0x000e; + rq.cparam = req; + rq.clen = sizeof(req); + rq.rparam = &buf; + rq.rlen = sizeof(buf); + + if (hci_send_req(dd, &rq, 1000) < 0) { + printf("\nCan't read revision info: %s (%d)\n", + strerror(errno), errno); + return; + } + + printf("\t%s\n", buf + 1); +} + +static void print_rev_broadcom(uint16_t hci_rev, uint16_t lmp_subver) +{ + printf("\tFirmware %d.%d / %d\n", + hci_rev & 0xff, lmp_subver >> 8, lmp_subver & 0xff); +} + +static void print_rev_avm(uint16_t hci_rev, uint16_t lmp_subver) +{ + if (lmp_subver == 0x01) + printf("\tFirmware 03.%d.%d\n", hci_rev >> 8, hci_rev & 0xff); + else + printf("\tUnknown type\n"); +} + +static void cmd_revision(int ctl, int hdev, char *opt) +{ + struct hci_version ver; + int dd; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + return; + } + + if (hci_read_local_version(dd, &ver, 1000) < 0) { + fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + return; + } + + print_dev_hdr(&di); + switch (ver.manufacturer) { + case 0: + case 37: + case 48: + print_rev_ericsson(dd); + break; + case 10: + print_rev_csr(dd, ver.hci_rev); + break; + case 12: + print_rev_digianswer(dd); + break; + case 15: + print_rev_broadcom(ver.hci_rev, ver.lmp_subver); + break; + case 31: + print_rev_avm(ver.hci_rev, ver.lmp_subver); + break; + default: + printf("\tUnsupported manufacturer\n"); + break; + } + return; +} + +static void cmd_block(int ctl, int hdev, char *opt) +{ + bdaddr_t bdaddr; + int dd; + + if (!opt) + return; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + str2ba(opt, &bdaddr); + + if (ioctl(dd, HCIBLOCKADDR, &bdaddr) < 0) { + perror("ioctl(HCIBLOCKADDR)"); + exit(1); + } + + hci_close_dev(dd); +} + +static void cmd_unblock(int ctl, int hdev, char *opt) +{ + bdaddr_t bdaddr; + int dd; + + if (!opt) + return; + + dd = hci_open_dev(hdev); + if (dd < 0) { + fprintf(stderr, "Can't open device hci%d: %s (%d)\n", + hdev, strerror(errno), errno); + exit(1); + } + + if (!strcasecmp(opt, "all")) + bacpy(&bdaddr, BDADDR_ANY); + else + str2ba(opt, &bdaddr); + + if (ioctl(dd, HCIUNBLOCKADDR, &bdaddr) < 0) { + perror("ioctl(HCIUNBLOCKADDR)"); + exit(1); + } + + hci_close_dev(dd); +} + +static void print_dev_hdr(struct hci_dev_info *di) +{ + static int hdr = -1; + char addr[18]; + + if (hdr == di->dev_id) + return; + hdr = di->dev_id; + + ba2str(&di->bdaddr, addr); + + printf("%s:\tType: %s Bus: %s\n", di->name, + hci_typetostr((di->type & 0x30) >> 4), + hci_bustostr(di->type & 0x0f)); + printf("\tBD Address: %s ACL MTU: %d:%d SCO MTU: %d:%d\n", + addr, di->acl_mtu, di->acl_pkts, + di->sco_mtu, di->sco_pkts); +} + +static void print_dev_info(int ctl, struct hci_dev_info *di) +{ + struct hci_dev_stats *st = &di->stat; + char *str; + + print_dev_hdr(di); + + str = hci_dflagstostr(di->flags); + printf("\t%s\n", str); + bt_free(str); + + printf("\tRX bytes:%d acl:%d sco:%d events:%d errors:%d\n", + st->byte_rx, st->acl_rx, st->sco_rx, st->evt_rx, st->err_rx); + + printf("\tTX bytes:%d acl:%d sco:%d commands:%d errors:%d\n", + st->byte_tx, st->acl_tx, st->sco_tx, st->cmd_tx, st->err_tx); + + if (all && !hci_test_bit(HCI_RAW, &di->flags)) { + print_dev_features(di, 0); + + if (((di->type & 0x30) >> 4) == HCI_BREDR) { + print_pkt_type(di); + print_link_policy(di); + print_link_mode(di); + + if (hci_test_bit(HCI_UP, &di->flags)) { + cmd_name(ctl, di->dev_id, NULL); + cmd_class(ctl, di->dev_id, NULL); + } + } + + if (hci_test_bit(HCI_UP, &di->flags)) + cmd_version(ctl, di->dev_id, NULL); + } + + printf("\n"); +} + +static struct { + char *cmd; + void (*func)(int ctl, int hdev, char *opt); + char *opt; + char *doc; +} command[] = { + { "up", cmd_up, 0, "Open and initialize HCI device" }, + { "down", cmd_down, 0, "Close HCI device" }, + { "reset", cmd_reset, 0, "Reset HCI device" }, + { "rstat", cmd_rstat, 0, "Reset statistic counters" }, + { "auth", cmd_auth, 0, "Enable Authentication" }, + { "noauth", cmd_auth, 0, "Disable Authentication" }, + { "encrypt", cmd_encrypt, 0, "Enable Encryption" }, + { "noencrypt", cmd_encrypt, 0, "Disable Encryption" }, + { "piscan", cmd_scan, 0, "Enable Page and Inquiry scan" }, + { "noscan", cmd_scan, 0, "Disable scan" }, + { "iscan", cmd_scan, 0, "Enable Inquiry scan" }, + { "pscan", cmd_scan, 0, "Enable Page scan" }, + { "ptype", cmd_ptype, "[type]", "Get/Set default packet type" }, + { "lm", cmd_lm, "[mode]", "Get/Set default link mode" }, + { "lp", cmd_lp, "[policy]", "Get/Set default link policy" }, + { "name", cmd_name, "[name]", "Get/Set local name" }, + { "class", cmd_class, "[class]", "Get/Set class of device" }, + { "voice", cmd_voice, "[voice]", "Get/Set voice setting" }, + { "iac", cmd_iac, "[iac]", "Get/Set inquiry access code" }, + { "inqtpl", cmd_inq_tpl, "[level]", "Get/Set inquiry transmit power level" }, + { "inqmode", cmd_inq_mode, "[mode]", "Get/Set inquiry mode" }, + { "inqdata", cmd_inq_data, "[data]", "Get/Set inquiry data" }, + { "inqtype", cmd_inq_type, "[type]", "Get/Set inquiry scan type" }, + { "inqparms", cmd_inq_parms, "[win:int]", "Get/Set inquiry scan window and interval" }, + { "pageparms", cmd_page_parms, "[win:int]", "Get/Set page scan window and interval" }, + { "pageto", cmd_page_to, "[to]", "Get/Set page timeout" }, + { "afhmode", cmd_afh_mode, "[mode]", "Get/Set AFH mode" }, + { "sspmode", cmd_ssp_mode, "[mode]", "Get/Set Simple Pairing Mode" }, + { "aclmtu", cmd_aclmtu, "", "Set ACL MTU and number of packets" }, + { "scomtu", cmd_scomtu, "", "Set SCO MTU and number of packets" }, + { "delkey", cmd_delkey, "", "Delete link key from the device" }, + { "oobdata", cmd_oob_data, 0, "Get local OOB data" }, + { "commands", cmd_commands, 0, "Display supported commands" }, + { "features", cmd_features, 0, "Display device features" }, + { "version", cmd_version, 0, "Display version information" }, + { "revision", cmd_revision, 0, "Display revision information" }, + { "block", cmd_block, "", "Add a device to the blacklist" }, + { "unblock", cmd_unblock, "", "Remove a device from the blacklist" }, + { "lerandaddr", cmd_le_addr, "", "Set LE Random Address" }, + { "leadv", cmd_le_adv, "[type]", "Enable LE advertising" + "\n\t\t\t0 - Connectable undirected advertising (default)" + "\n\t\t\t3 - Non connectable undirected advertising"}, + { "noleadv", cmd_no_le_adv, 0, "Disable LE advertising" }, + { "lestates", cmd_le_states, 0, "Display the supported LE states" }, + { NULL, NULL, 0 } +}; + +static void usage(void) +{ + int i; + + printf("hciconfig - HCI device configuration utility\n"); + printf("Usage:\n" + "\thciconfig\n" + "\thciconfig [-a] hciX [command ...]\n"); + printf("Commands:\n"); + for (i = 0; command[i].cmd; i++) + printf("\t%-10s %-8s\t%s\n", command[i].cmd, + command[i].opt ? command[i].opt : " ", + command[i].doc); +} + +static struct option main_options[] = { + { "help", 0, 0, 'h' }, + { "all", 0, 0, 'a' }, + { 0, 0, 0, 0 } +}; + +int main(int argc, char *argv[]) +{ + int opt, ctl, i, cmd = 0; + + while ((opt = getopt_long(argc, argv, "ah", main_options, NULL)) != -1) { + switch (opt) { + case 'a': + all = 1; + break; + + case 'h': + default: + usage(); + exit(0); + } + } + + argc -= optind; + argv += optind; + optind = 0; + + /* Open HCI socket */ + if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) { + perror("Can't open HCI socket."); + exit(1); + } + + if (argc < 1) { + print_dev_list(ctl, 0); + exit(0); + } + + di.dev_id = atoi(argv[0] + 3); + argc--; argv++; + + if (ioctl(ctl, HCIGETDEVINFO, (void *) &di)) { + perror("Can't get device info"); + exit(1); + } + + if (hci_test_bit(HCI_RAW, &di.flags) && + !bacmp(&di.bdaddr, BDADDR_ANY)) { + int dd = hci_open_dev(di.dev_id); + hci_read_bd_addr(dd, &di.bdaddr, 1000); + hci_close_dev(dd); + } + + while (argc > 0) { + for (i = 0; command[i].cmd; i++) { + if (strncmp(command[i].cmd, + *argv, strlen(command[i].cmd))) + continue; + + if (command[i].opt) { + argc--; argv++; + } + + command[i].func(ctl, di.dev_id, *argv); + cmd = 1; + break; + } + + if (command[i].cmd == 0) + fprintf(stderr, "Warning: unknown command - \"%s\"\n", + *argv); + + argc--; argv++; + } + + if (!cmd) + print_dev_info(ctl, &di); + + close(ctl); + return 0; +} diff --git a/external/cache/sources/hcitools/hcitool.c b/external/cache/sources/hcitools/hcitool.c new file mode 100644 index 0000000..aa58efc --- /dev/null +++ b/external/cache/sources/hcitools/hcitool.c @@ -0,0 +1,3122 @@ +/* + * + * 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 + +/* Unofficial value, might still change */ +#define LE_LINK 0x03 + +#define FLAGS_AD_TYPE 0x01 +#define FLAGS_LIMITED_MODE_BIT 0x01 +#define FLAGS_GENERAL_MODE_BIT 0x02 + +#define EIR_FLAGS 0x01 /* flags */ +#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ +#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ +#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */ +#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ +#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */ +#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ +#define EIR_NAME_SHORT 0x08 /* shortened local name */ +#define EIR_NAME_COMPLETE 0x09 /* complete local name */ +#define EIR_TX_POWER 0x0A /* transmit power level */ +#define EIR_DEVICE_ID 0x10 /* device ID */ + +#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, NULL)) != -1) + +static volatile int signal_received = 0; + +static void usage(void); + +static char *batocomp(const bdaddr_t *ba) +{ + return NULL; +} + +static int dev_info(int s, int dev_id, long arg) +{ + struct hci_dev_info di = { .dev_id = dev_id }; + char addr[18]; + + if (ioctl(s, HCIGETDEVINFO, (void *) &di)) + return 0; + + ba2str(&di.bdaddr, addr); + printf("\t%s\t%s\n", di.name, addr); + return 0; +} + +static void helper_arg(int min_num_arg, int max_num_arg, int *argc, + char ***argv, const char *usage) +{ + *argc -= optind; + /* too many arguments, but when "max_num_arg < min_num_arg" then no + limiting (prefer "max_num_arg=-1" to gen infinity) + */ + if ( (*argc > max_num_arg) && (max_num_arg >= min_num_arg ) ) { + fprintf(stderr, "%s: too many arguments (maximal: %i)\n", + *argv[0], max_num_arg); + printf("%s", usage); + exit(1); + } + + /* print usage */ + if (*argc < min_num_arg) { + fprintf(stderr, "%s: too few arguments (minimal: %i)\n", + *argv[0], min_num_arg); + printf("%s", usage); + exit(0); + } + + *argv += optind; +} + +static char *type2str(uint8_t type) +{ + switch (type) { + case SCO_LINK: + return "SCO"; + case ACL_LINK: + return "ACL"; + case ESCO_LINK: + return "eSCO"; + case LE_LINK: + return "LE"; + default: + return "Unknown"; + } +} + +static int conn_list(int s, int dev_id, long arg) +{ + struct hci_conn_list_req *cl; + struct hci_conn_info *ci; + int id = arg; + int i; + + if (id != -1 && dev_id != id) + return 0; + + if (!(cl = malloc(10 * sizeof(*ci) + sizeof(*cl)))) { + perror("Can't allocate memory"); + exit(1); + } + cl->dev_id = dev_id; + cl->conn_num = 10; + ci = cl->conn_info; + + if (ioctl(s, HCIGETCONNLIST, (void *) cl)) { + perror("Can't get connection list"); + exit(1); + } + + for (i = 0; i < cl->conn_num; i++, ci++) { + char addr[18]; + char *str; + ba2str(&ci->bdaddr, addr); + str = hci_lmtostr(ci->link_mode); + printf("\t%s %s %s handle %d state %d lm %s\n", + ci->out ? "<" : ">", type2str(ci->type), + addr, ci->handle, ci->state, str); + bt_free(str); + } + + free(cl); + return 0; +} + +static int find_conn(int s, int dev_id, long arg) +{ + struct hci_conn_list_req *cl; + struct hci_conn_info *ci; + int i; + + if (!(cl = malloc(10 * sizeof(*ci) + sizeof(*cl)))) { + perror("Can't allocate memory"); + exit(1); + } + cl->dev_id = dev_id; + cl->conn_num = 10; + ci = cl->conn_info; + + if (ioctl(s, HCIGETCONNLIST, (void *) cl)) { + perror("Can't get connection list"); + exit(1); + } + + for (i = 0; i < cl->conn_num; i++, ci++) + if (!bacmp((bdaddr_t *) arg, &ci->bdaddr)) { + free(cl); + return 1; + } + + free(cl); + return 0; +} + +static void hex_dump(char *pref, int width, unsigned char *buf, int len) +{ + register int i,n; + + for (i = 0, n = 1; i < len; i++, n++) { + if (n == 1) + printf("%s", pref); + printf("%2.2X ", buf[i]); + if (n == width) { + printf("\n"); + n = 0; + } + } + if (i && n!=1) + printf("\n"); +} + +static char *get_minor_device_name(int major, int minor) +{ + switch (major) { + case 0: /* misc */ + return ""; + case 1: /* computer */ + switch (minor) { + case 0: + return "Uncategorized"; + case 1: + return "Desktop workstation"; + case 2: + return "Server"; + case 3: + return "Laptop"; + case 4: + return "Handheld"; + case 5: + return "Palm"; + case 6: + return "Wearable"; + } + break; + case 2: /* phone */ + switch (minor) { + case 0: + return "Uncategorized"; + case 1: + return "Cellular"; + case 2: + return "Cordless"; + case 3: + return "Smart phone"; + case 4: + return "Wired modem or voice gateway"; + case 5: + return "Common ISDN Access"; + case 6: + return "Sim Card Reader"; + } + break; + case 3: /* lan access */ + if (minor == 0) + return "Uncategorized"; + switch (minor / 8) { + case 0: + return "Fully available"; + case 1: + return "1-17% utilized"; + case 2: + return "17-33% utilized"; + case 3: + return "33-50% utilized"; + case 4: + return "50-67% utilized"; + case 5: + return "67-83% utilized"; + case 6: + return "83-99% utilized"; + case 7: + return "No service available"; + } + break; + case 4: /* audio/video */ + switch (minor) { + case 0: + return "Uncategorized"; + case 1: + return "Device conforms to the Headset profile"; + case 2: + return "Hands-free"; + /* 3 is reserved */ + case 4: + return "Microphone"; + case 5: + return "Loudspeaker"; + case 6: + return "Headphones"; + case 7: + return "Portable Audio"; + case 8: + return "Car Audio"; + case 9: + return "Set-top box"; + case 10: + return "HiFi Audio Device"; + case 11: + return "VCR"; + case 12: + return "Video Camera"; + case 13: + return "Camcorder"; + case 14: + return "Video Monitor"; + case 15: + return "Video Display and Loudspeaker"; + case 16: + return "Video Conferencing"; + /* 17 is reserved */ + case 18: + return "Gaming/Toy"; + } + break; + case 5: /* peripheral */ { + static char cls_str[48]; cls_str[0] = 0; + + switch (minor & 48) { + case 16: + strncpy(cls_str, "Keyboard", sizeof(cls_str)); + break; + case 32: + strncpy(cls_str, "Pointing device", sizeof(cls_str)); + break; + case 48: + strncpy(cls_str, "Combo keyboard/pointing device", sizeof(cls_str)); + break; + } + if ((minor & 15) && (strlen(cls_str) > 0)) + strcat(cls_str, "/"); + + switch (minor & 15) { + case 0: + break; + case 1: + strncat(cls_str, "Joystick", sizeof(cls_str) - strlen(cls_str)); + break; + case 2: + strncat(cls_str, "Gamepad", sizeof(cls_str) - strlen(cls_str)); + break; + case 3: + strncat(cls_str, "Remote control", sizeof(cls_str) - strlen(cls_str)); + break; + case 4: + strncat(cls_str, "Sensing device", sizeof(cls_str) - strlen(cls_str)); + break; + case 5: + strncat(cls_str, "Digitizer tablet", sizeof(cls_str) - strlen(cls_str)); + break; + case 6: + strncat(cls_str, "Card reader", sizeof(cls_str) - strlen(cls_str)); + break; + default: + strncat(cls_str, "(reserved)", sizeof(cls_str) - strlen(cls_str)); + break; + } + if (strlen(cls_str) > 0) + return cls_str; + } + case 6: /* imaging */ + if (minor & 4) + return "Display"; + if (minor & 8) + return "Camera"; + if (minor & 16) + return "Scanner"; + if (minor & 32) + return "Printer"; + break; + case 7: /* wearable */ + switch (minor) { + case 1: + return "Wrist Watch"; + case 2: + return "Pager"; + case 3: + return "Jacket"; + case 4: + return "Helmet"; + case 5: + return "Glasses"; + } + break; + case 8: /* toy */ + switch (minor) { + case 1: + return "Robot"; + case 2: + return "Vehicle"; + case 3: + return "Doll / Action Figure"; + case 4: + return "Controller"; + case 5: + return "Game"; + } + break; + case 63: /* uncategorised */ + return ""; + } + return "Unknown (reserved) minor device class"; +} + +static char *major_classes[] = { + "Miscellaneous", "Computer", "Phone", "LAN Access", + "Audio/Video", "Peripheral", "Imaging", "Uncategorized" +}; + +static char *get_device_name(const bdaddr_t *local, const bdaddr_t *peer) +{ +#if 0 + char filename[PATH_MAX + 1]; + char local_addr[18], peer_addr[18]; + GKeyFile *key_file; + char *str = NULL; + int len; + + ba2str(local, local_addr); + ba2str(peer, peer_addr); + + snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local_addr, + peer_addr); + filename[PATH_MAX] = '\0'; + key_file = g_key_file_new(); + + if (g_key_file_load_from_file(key_file, filename, 0, NULL)) { + str = g_key_file_get_string(key_file, "General", "Name", NULL); + if (str) { + len = strlen(str); + if (len > HCI_MAX_NAME_LENGTH) + str[HCI_MAX_NAME_LENGTH] = '\0'; + } + } + + g_key_file_free(key_file); + + return str; +#endif + return NULL; +} + +/* Display local devices */ + +static struct option dev_options[] = { + { "help", 0, 0, 'h' }, + {0, 0, 0, 0 } +}; + +static const char *dev_help = + "Usage:\n" + "\tdev\n"; + +static void cmd_dev(int dev_id, int argc, char **argv) +{ + int opt; + + for_each_opt(opt, dev_options, NULL) { + switch (opt) { + default: + printf("%s", dev_help); + return; + } + } + helper_arg(0, 0, &argc, &argv, dev_help); + + printf("Devices:\n"); + + hci_for_each_dev(HCI_UP, dev_info, 0); +} + +/* Inquiry */ + +static struct option inq_options[] = { + { "help", 0, 0, 'h' }, + { "length", 1, 0, 'l' }, + { "numrsp", 1, 0, 'n' }, + { "iac", 1, 0, 'i' }, + { "flush", 0, 0, 'f' }, + { 0, 0, 0, 0 } +}; + +static const char *inq_help = + "Usage:\n" + "\tinq [--length=N] maximum inquiry duration in 1.28 s units\n" + "\t [--numrsp=N] specify maximum number of inquiry responses\n" + "\t [--iac=lap] specify the inquiry access code\n" + "\t [--flush] flush the inquiry cache\n"; + +static void cmd_inq(int dev_id, int argc, char **argv) +{ + inquiry_info *info = NULL; + uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; + int num_rsp, length, flags; + char addr[18]; + int i, l, opt; + + length = 8; /* ~10 seconds */ + num_rsp = 0; + flags = 0; + + for_each_opt(opt, inq_options, NULL) { + switch (opt) { + case 'l': + length = atoi(optarg); + break; + + case 'n': + num_rsp = atoi(optarg); + break; + + case 'i': + l = strtoul(optarg, 0, 16); + if (!strcasecmp(optarg, "giac")) { + l = 0x9e8b33; + } else if (!strcasecmp(optarg, "liac")) { + l = 0x9e8b00; + } if (l < 0x9e8b00 || l > 0x9e8b3f) { + printf("Invalid access code 0x%x\n", l); + exit(1); + } + lap[0] = (l & 0xff); + lap[1] = (l >> 8) & 0xff; + lap[2] = (l >> 16) & 0xff; + break; + + case 'f': + flags |= IREQ_CACHE_FLUSH; + break; + + default: + printf("%s", inq_help); + return; + } + } + helper_arg(0, 0, &argc, &argv, inq_help); + + printf("Inquiring ...\n"); + + num_rsp = hci_inquiry(dev_id, length, num_rsp, lap, &info, flags); + if (num_rsp < 0) { + perror("Inquiry failed."); + exit(1); + } + + for (i = 0; i < num_rsp; i++) { + ba2str(&(info+i)->bdaddr, addr); + printf("\t%s\tclock offset: 0x%4.4x\tclass: 0x%2.2x%2.2x%2.2x\n", + addr, btohs((info+i)->clock_offset), + (info+i)->dev_class[2], + (info+i)->dev_class[1], + (info+i)->dev_class[0]); + } + + bt_free(info); +} + +/* Device scanning */ + +static struct option scan_options[] = { + { "help", 0, 0, 'h' }, + { "length", 1, 0, 'l' }, + { "numrsp", 1, 0, 'n' }, + { "iac", 1, 0, 'i' }, + { "flush", 0, 0, 'f' }, + { "refresh", 0, 0, 'r' }, + { "class", 0, 0, 'C' }, + { "info", 0, 0, 'I' }, + { "oui", 0, 0, 'O' }, + { "all", 0, 0, 'A' }, + { "ext", 0, 0, 'A' }, + { 0, 0, 0, 0 } +}; + +static const char *scan_help = + "Usage:\n" + "\tscan [--length=N] [--numrsp=N] [--iac=lap] [--flush] [--class] [--info] [--oui] [--refresh]\n"; + +static void cmd_scan(int dev_id, int argc, char **argv) +{ + inquiry_info *info = NULL; + uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; + int num_rsp, length, flags; + uint8_t cls[3], features[8]; + char addr[18], name[249], *comp, *tmp; + struct hci_version version; + struct hci_dev_info di; + struct hci_conn_info_req *cr; + int refresh = 0, extcls = 0, extinf = 0, extoui = 0; + int i, n, l, opt, dd, cc, nc; + + length = 8; /* ~10 seconds */ + num_rsp = 0; + flags = 0; + + for_each_opt(opt, scan_options, NULL) { + switch (opt) { + case 'l': + length = atoi(optarg); + break; + + case 'n': + num_rsp = atoi(optarg); + break; + + case 'i': + l = strtoul(optarg, 0, 16); + if (!strcasecmp(optarg, "giac")) { + l = 0x9e8b33; + } else if (!strcasecmp(optarg, "liac")) { + l = 0x9e8b00; + } else if (l < 0x9e8b00 || l > 0x9e8b3f) { + printf("Invalid access code 0x%x\n", l); + exit(1); + } + lap[0] = (l & 0xff); + lap[1] = (l >> 8) & 0xff; + lap[2] = (l >> 16) & 0xff; + break; + + case 'f': + flags |= IREQ_CACHE_FLUSH; + break; + + case 'r': + refresh = 1; + break; + + case 'C': + extcls = 1; + break; + + case 'I': + extinf = 1; + break; + + case 'O': + extoui = 1; + break; + + case 'A': + extcls = 1; + extinf = 1; + extoui = 1; + break; + + default: + printf("%s", scan_help); + return; + } + } + helper_arg(0, 0, &argc, &argv, scan_help); + + if (dev_id < 0) { + dev_id = hci_get_route(NULL); + if (dev_id < 0) { + perror("Device is not available"); + exit(1); + } + } + + if (hci_devinfo(dev_id, &di) < 0) { + perror("Can't get device info"); + exit(1); + } + + printf("Scanning ...\n"); + num_rsp = hci_inquiry(dev_id, length, num_rsp, lap, &info, flags); + if (num_rsp < 0) { + perror("Inquiry failed"); + exit(1); + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + free(info); + exit(1); + } + + if (extcls || extinf || extoui) + printf("\n"); + + for (i = 0; i < num_rsp; i++) { + uint16_t handle = 0; + + if (!refresh) { + memset(name, 0, sizeof(name)); + tmp = get_device_name(&di.bdaddr, &(info+i)->bdaddr); + if (tmp) { + strncpy(name, tmp, 249); + free(tmp); + nc = 1; + } else + nc = 0; + } else + nc = 0; + + if (!extcls && !extinf && !extoui) { + ba2str(&(info+i)->bdaddr, addr); + + if (nc) { + printf("\t%s\t%s\n", addr, name); + continue; + } + + if (hci_read_remote_name_with_clock_offset(dd, + &(info+i)->bdaddr, + (info+i)->pscan_rep_mode, + (info+i)->clock_offset | 0x8000, + sizeof(name), name, 100000) < 0) + strcpy(name, "n/a"); + + for (n = 0; n < 248 && name[n]; n++) { + if ((unsigned char) name[i] < 32 || name[i] == 127) + name[i] = '.'; + } + + name[248] = '\0'; + + printf("\t%s\t%s\n", addr, name); + continue; + } + + ba2str(&(info+i)->bdaddr, addr); + printf("BD Address:\t%s [mode %d, clkoffset 0x%4.4x]\n", addr, + (info+i)->pscan_rep_mode, btohs((info+i)->clock_offset)); + + if (extoui) { + comp = batocomp(&(info+i)->bdaddr); + if (comp) { + char oui[9]; + ba2oui(&(info+i)->bdaddr, oui); + printf("OUI company:\t%s (%s)\n", comp, oui); + free(comp); + } + } + + cc = 0; + + if (extinf) { + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (cr) { + bacpy(&cr->bdaddr, &(info+i)->bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + handle = 0; + cc = 1; + } else { + handle = htobs(cr->conn_info->handle); + cc = 0; + } + free(cr); + } + + if (cc) { + if (hci_create_connection(dd, &(info+i)->bdaddr, + htobs(di.pkt_type & ACL_PTYPE_MASK), + (info+i)->clock_offset | 0x8000, + 0x01, &handle, 25000) < 0) { + handle = 0; + cc = 0; + } + } + } + + if (handle > 0 || !nc) { + if (hci_read_remote_name_with_clock_offset(dd, + &(info+i)->bdaddr, + (info+i)->pscan_rep_mode, + (info+i)->clock_offset | 0x8000, + sizeof(name), name, 100000) < 0) { + if (!nc) + strcpy(name, "n/a"); + } else { + for (n = 0; n < 248 && name[n]; n++) { + if ((unsigned char) name[i] < 32 || name[i] == 127) + name[i] = '.'; + } + + name[248] = '\0'; + nc = 0; + } + } + + if (strlen(name) > 0) + printf("Device name:\t%s%s\n", name, nc ? " [cached]" : ""); + + if (extcls) { + memcpy(cls, (info+i)->dev_class, 3); + printf("Device class:\t"); + if ((cls[1] & 0x1f) > sizeof(major_classes) / sizeof(char *)) + printf("Invalid"); + else + printf("%s, %s", major_classes[cls[1] & 0x1f], + get_minor_device_name(cls[1] & 0x1f, cls[0] >> 2)); + printf(" (0x%2.2x%2.2x%2.2x)\n", cls[2], cls[1], cls[0]); + } + + if (extinf && handle > 0) { + if (hci_read_remote_version(dd, handle, &version, 20000) == 0) { + char *ver = lmp_vertostr(version.lmp_ver); + printf("Manufacturer:\t%s (%d)\n", + bt_compidtostr(version.manufacturer), + version.manufacturer); + printf("LMP version:\t%s (0x%x) [subver 0x%x]\n", + ver ? ver : "n/a", + version.lmp_ver, version.lmp_subver); + if (ver) + bt_free(ver); + } + + if (hci_read_remote_features(dd, handle, features, 20000) == 0) { + char *tmp = lmp_featurestostr(features, "\t\t", 63); + printf("LMP features:\t0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x" + " 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", + features[0], features[1], + features[2], features[3], + features[4], features[5], + features[6], features[7]); + printf("%s\n", tmp); + bt_free(tmp); + } + + if (cc) { + usleep(10000); + hci_disconnect(dd, handle, HCI_OE_USER_ENDED_CONNECTION, 10000); + } + } + + printf("\n"); + } + + bt_free(info); + + hci_close_dev(dd); +} + +/* Remote name */ + +static struct option name_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *name_help = + "Usage:\n" + "\tname \n"; + +static void cmd_name(int dev_id, int argc, char **argv) +{ + bdaddr_t bdaddr; + char name[248]; + int opt, dd; + + for_each_opt(opt, name_options, NULL) { + switch (opt) { + default: + printf("%s", name_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, name_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_get_route(&bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Device is not available.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + if (hci_read_remote_name(dd, &bdaddr, sizeof(name), name, 25000) == 0) + printf("%s\n", name); + + hci_close_dev(dd); +} + +/* Info about remote device */ + +static struct option info_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *info_help = + "Usage:\n" + "\tinfo \n"; + +static void cmd_info(int dev_id, int argc, char **argv) +{ + bdaddr_t bdaddr; + uint16_t handle; + uint8_t features[8], max_page = 0; + char name[249], *comp, *tmp; + struct hci_version version; + struct hci_dev_info di; + struct hci_conn_info_req *cr; + int i, opt, dd, cc = 0; + + for_each_opt(opt, info_options, NULL) { + switch (opt) { + default: + printf("%s", info_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, info_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + + if (dev_id < 0) + dev_id = hci_get_route(&bdaddr); + + if (dev_id < 0) { + fprintf(stderr, "Device is not available or not connected.\n"); + exit(1); + } + + if (hci_devinfo(dev_id, &di) < 0) { + perror("Can't get device info"); + exit(1); + } + + printf("Requesting information ...\n"); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't get connection info"); + close(dd); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + if (hci_create_connection(dd, &bdaddr, + htobs(di.pkt_type & ACL_PTYPE_MASK), + 0, 0x01, &handle, 25000) < 0) { + perror("Can't create connection"); + close(dd); + exit(1); + } + sleep(1); + cc = 1; + } else + handle = htobs(cr->conn_info->handle); + + printf("\tBD Address: %s\n", argv[0]); + + comp = batocomp(&bdaddr); + if (comp) { + char oui[9]; + ba2oui(&bdaddr, oui); + printf("\tOUI Company: %s (%s)\n", comp, oui); + free(comp); + } + + if (hci_read_remote_name(dd, &bdaddr, sizeof(name), name, 25000) == 0) + printf("\tDevice Name: %s\n", name); + + if (hci_read_remote_version(dd, handle, &version, 20000) == 0) { + char *ver = lmp_vertostr(version.lmp_ver); + printf("\tLMP Version: %s (0x%x) LMP Subversion: 0x%x\n" + "\tManufacturer: %s (%d)\n", + ver ? ver : "n/a", + version.lmp_ver, + version.lmp_subver, + bt_compidtostr(version.manufacturer), + version.manufacturer); + if (ver) + bt_free(ver); + } + + memset(features, 0, sizeof(features)); + hci_read_remote_features(dd, handle, features, 20000); + + if ((di.features[7] & LMP_EXT_FEAT) && (features[7] & LMP_EXT_FEAT)) + hci_read_remote_ext_features(dd, handle, 0, &max_page, + features, 20000); + + printf("\tFeatures%s: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", + (max_page > 0) ? " page 0" : "", + features[0], features[1], features[2], features[3], + features[4], features[5], features[6], features[7]); + + tmp = lmp_featurestostr(features, "\t\t", 63); + printf("%s\n", tmp); + bt_free(tmp); + + for (i = 1; i <= max_page; i++) { + if (hci_read_remote_ext_features(dd, handle, i, NULL, + features, 20000) < 0) + continue; + + printf("\tFeatures page %d: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " + "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", i, + features[0], features[1], features[2], features[3], + features[4], features[5], features[6], features[7]); + } + + if (cc) { + usleep(10000); + hci_disconnect(dd, handle, HCI_OE_USER_ENDED_CONNECTION, 10000); + } + + hci_close_dev(dd); +} + +/* Start periodic inquiry */ + +static struct option spinq_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *spinq_help = + "Usage:\n" + "\tspinq\n"; + +static void cmd_spinq(int dev_id, int argc, char **argv) +{ + uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; + struct hci_request rq; + periodic_inquiry_cp cp; + int opt, dd; + + for_each_opt(opt, spinq_options, NULL) { + switch (opt) { + default: + printf("%s", spinq_help); + return; + } + } + helper_arg(0, 0, &argc, &argv, spinq_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Device open failed"); + exit(EXIT_FAILURE); + } + + memset(&cp, 0, sizeof(cp)); + memcpy(cp.lap, lap, 3); + cp.max_period = htobs(16); + cp.min_period = htobs(10); + cp.length = 8; + cp.num_rsp = 0; + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_LINK_CTL; + rq.ocf = OCF_PERIODIC_INQUIRY; + rq.cparam = &cp; + rq.clen = PERIODIC_INQUIRY_CP_SIZE; + + if (hci_send_req(dd, &rq, 100) < 0) { + perror("Periodic inquiry failed"); + exit(EXIT_FAILURE); + } + + hci_close_dev(dd); +} + +/* Exit periodic inquiry */ + +static struct option epinq_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *epinq_help = + "Usage:\n" + "\tepinq\n"; + +static void cmd_epinq(int dev_id, int argc, char **argv) +{ + int opt, dd; + + for_each_opt(opt, epinq_options, NULL) { + switch (opt) { + default: + printf("%s", epinq_help); + return; + } + } + helper_arg(0, 0, &argc, &argv, epinq_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Device open failed"); + exit(EXIT_FAILURE); + } + + if (hci_send_cmd(dd, OGF_LINK_CTL, + OCF_EXIT_PERIODIC_INQUIRY, 0, NULL) < 0) { + perror("Exit periodic inquiry failed"); + exit(EXIT_FAILURE); + } + + hci_close_dev(dd); +} + +/* Send arbitrary HCI commands */ + +static struct option cmd_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *cmd_help = + "Usage:\n" + "\tcmd [parameters]\n" + "Example:\n" + "\tcmd 0x03 0x0013 0x41 0x42 0x43 0x44\n"; + +static void cmd_cmd(int dev_id, int argc, char **argv) +{ + unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf; + struct hci_filter flt; + hci_event_hdr *hdr; + int i, opt, len, dd; + uint16_t ocf; + uint8_t ogf; + + for_each_opt(opt, cmd_options, NULL) { + switch (opt) { + default: + printf("%s", cmd_help); + return; + } + } + helper_arg(2, -1, &argc, &argv, cmd_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + errno = 0; + ogf = strtol(argv[0], NULL, 16); + ocf = strtol(argv[1], NULL, 16); + if (errno == ERANGE || (ogf > 0x3f) || (ocf > 0x3ff)) { + printf("%s", cmd_help); + return; + } + + for (i = 2, len = 0; i < argc && len < (int) sizeof(buf); i++, len++) + *ptr++ = (uint8_t) strtol(argv[i], NULL, 16); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Device open failed"); + exit(EXIT_FAILURE); + } + + /* Setup filter */ + hci_filter_clear(&flt); + hci_filter_set_ptype(HCI_EVENT_PKT, &flt); + hci_filter_all_events(&flt); + if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { + perror("HCI filter setup failed"); + exit(EXIT_FAILURE); + } + + printf("< HCI Command: ogf 0x%02x, ocf 0x%04x, plen %d\n", ogf, ocf, len); + hex_dump(" ", 20, buf, len); fflush(stdout); + + if (hci_send_cmd(dd, ogf, ocf, len, buf) < 0) { + perror("Send failed"); + exit(EXIT_FAILURE); + } + + len = read(dd, buf, sizeof(buf)); + if (len < 0) { + perror("Read failed"); + exit(EXIT_FAILURE); + } + + hdr = (void *)(buf + 1); + ptr = buf + (1 + HCI_EVENT_HDR_SIZE); + len -= (1 + HCI_EVENT_HDR_SIZE); + + printf("> HCI Event: 0x%02x plen %d\n", hdr->evt, hdr->plen); + hex_dump(" ", 20, ptr, len); fflush(stdout); + + hci_close_dev(dd); +} + +/* Display active connections */ + +static struct option con_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *con_help = + "Usage:\n" + "\tcon\n"; + +static void cmd_con(int dev_id, int argc, char **argv) +{ + int opt; + + for_each_opt(opt, con_options, NULL) { + switch (opt) { + default: + printf("%s", con_help); + return; + } + } + helper_arg(0, 0, &argc, &argv, con_help); + + printf("Connections:\n"); + + hci_for_each_dev(HCI_UP, conn_list, dev_id); +} + +/* Create connection */ + +static struct option cc_options[] = { + { "help", 0, 0, 'h' }, + { "role", 1, 0, 'r' }, + { "ptype", 1, 0, 'p' }, + { 0, 0, 0, 0 } +}; + +static const char *cc_help = + "Usage:\n" + "\tcc [--role=m|s] [--ptype=pkt_types] \n" + "Example:\n" + "\tcc --ptype=dm1,dh3,dh5 01:02:03:04:05:06\n" + "\tcc --role=m 01:02:03:04:05:06\n"; + +static void cmd_cc(int dev_id, int argc, char **argv) +{ + bdaddr_t bdaddr; + uint16_t handle; + uint8_t role; + unsigned int ptype; + int dd, opt; + + role = 0x01; + ptype = HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5; + + for_each_opt(opt, cc_options, NULL) { + switch (opt) { + case 'p': + hci_strtoptype(optarg, &ptype); + break; + + case 'r': + role = optarg[0] == 'm' ? 0 : 1; + break; + + default: + printf("%s", cc_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, cc_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_get_route(&bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Device is not available.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + if (hci_create_connection(dd, &bdaddr, htobs(ptype), + htobs(0x0000), role, &handle, 25000) < 0) + perror("Can't create connection"); + + hci_close_dev(dd); +} + +/* Close connection */ + +static struct option dc_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *dc_help = + "Usage:\n" + "\tdc [reason]\n"; + +static void cmd_dc(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint8_t reason; + int opt, dd; + + for_each_opt(opt, dc_options, NULL) { + switch (opt) { + default: + printf("%s", dc_help); + return; + } + } + helper_arg(1, 2, &argc, &argv, dc_help); + + str2ba(argv[0], &bdaddr); + reason = (argc > 1) ? atoi(argv[1]) : HCI_OE_USER_ENDED_CONNECTION; + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (hci_disconnect(dd, htobs(cr->conn_info->handle), + reason, 10000) < 0) + perror("Disconnect failed"); + + free(cr); + + hci_close_dev(dd); +} + +/* Role switch */ + +static struct option sr_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *sr_help = + "Usage:\n" + "\tsr \n"; + +static void cmd_sr(int dev_id, int argc, char **argv) +{ + bdaddr_t bdaddr; + uint8_t role; + int opt, dd; + + for_each_opt(opt, sr_options, NULL) { + switch (opt) { + default: + printf("%s", sr_help); + return; + } + } + helper_arg(2, 2, &argc, &argv, sr_help); + + str2ba(argv[0], &bdaddr); + switch (argv[1][0]) { + case 'm': + role = 0; + break; + case 's': + role = 1; + break; + default: + role = atoi(argv[1]); + break; + } + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + if (hci_switch_role(dd, &bdaddr, role, 10000) < 0) { + perror("Switch role request failed"); + exit(1); + } + + hci_close_dev(dd); +} + +/* Read RSSI */ + +static struct option rssi_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *rssi_help = + "Usage:\n" + "\trssi \n"; + +static void cmd_rssi(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + int8_t rssi; + int opt, dd; + + for_each_opt(opt, rssi_options, NULL) { + switch (opt) { + default: + printf("%s", rssi_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, rssi_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (hci_read_rssi(dd, htobs(cr->conn_info->handle), &rssi, 1000) < 0) { + perror("Read RSSI failed"); + exit(1); + } + + printf("RSSI return value: %d\n", rssi); + + free(cr); + + hci_close_dev(dd); +} + +/* Get link quality */ + +static struct option lq_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *lq_help = + "Usage:\n" + "\tlq \n"; + +static void cmd_lq(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint8_t lq; + int opt, dd; + + for_each_opt(opt, lq_options, NULL) { + switch (opt) { + default: + printf("%s", lq_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, lq_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (hci_read_link_quality(dd, htobs(cr->conn_info->handle), &lq, 1000) < 0) { + perror("HCI read_link_quality request failed"); + exit(1); + } + + printf("Link quality: %d\n", lq); + + free(cr); + + hci_close_dev(dd); +} + +/* Get transmit power level */ + +static struct option tpl_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *tpl_help = + "Usage:\n" + "\ttpl [type]\n"; + +static void cmd_tpl(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint8_t type; + int8_t level; + int opt, dd; + + for_each_opt(opt, tpl_options, NULL) { + switch (opt) { + default: + printf("%s", tpl_help); + return; + } + } + helper_arg(1, 2, &argc, &argv, tpl_help); + + str2ba(argv[0], &bdaddr); + type = (argc > 1) ? atoi(argv[1]) : 0; + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (hci_read_transmit_power_level(dd, htobs(cr->conn_info->handle), type, &level, 1000) < 0) { + perror("HCI read transmit power level request failed"); + exit(1); + } + + printf("%s transmit power level: %d\n", + (type == 0) ? "Current" : "Maximum", level); + + free(cr); + + hci_close_dev(dd); +} + +/* Get AFH channel map */ + +static struct option afh_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *afh_help = + "Usage:\n" + "\tafh \n"; + +static void cmd_afh(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint16_t handle; + uint8_t mode, map[10]; + int opt, dd; + + for_each_opt(opt, afh_options, NULL) { + switch (opt) { + default: + printf("%s", afh_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, afh_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + handle = htobs(cr->conn_info->handle); + + if (hci_read_afh_map(dd, handle, &mode, map, 1000) < 0) { + perror("HCI read AFH map request failed"); + exit(1); + } + + if (mode == 0x01) { + int i; + printf("AFH map: 0x"); + for (i = 0; i < 10; i++) + printf("%02x", map[i]); + printf("\n"); + } else + printf("AFH disabled\n"); + + free(cr); + + hci_close_dev(dd); +} + +/* Set connection packet type */ + +static struct option cpt_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *cpt_help = + "Usage:\n" + "\tcpt \n"; + +static void cmd_cpt(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + struct hci_request rq; + set_conn_ptype_cp cp; + evt_conn_ptype_changed rp; + bdaddr_t bdaddr; + unsigned int ptype; + int dd, opt; + + for_each_opt(opt, cpt_options, NULL) { + switch (opt) { + default: + printf("%s", cpt_help); + return; + } + } + helper_arg(2, 2, &argc, &argv, cpt_help); + + str2ba(argv[0], &bdaddr); + hci_strtoptype(argv[1], &ptype); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + cp.handle = htobs(cr->conn_info->handle); + cp.pkt_type = ptype; + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_LINK_CTL; + rq.ocf = OCF_SET_CONN_PTYPE; + rq.cparam = &cp; + rq.clen = SET_CONN_PTYPE_CP_SIZE; + rq.rparam = &rp; + rq.rlen = EVT_CONN_PTYPE_CHANGED_SIZE; + rq.event = EVT_CONN_PTYPE_CHANGED; + + if (hci_send_req(dd, &rq, 100) < 0) { + perror("Packet type change failed"); + exit(1); + } + + free(cr); + + hci_close_dev(dd); +} + +/* Get/Set link policy settings */ + +static struct option lp_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *lp_help = + "Usage:\n" + "\tlp [link policy]\n"; + +static void cmd_lp(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint16_t policy; + int opt, dd; + + for_each_opt(opt, lp_options, NULL) { + switch (opt) { + default: + printf("%s", lp_help); + return; + } + } + helper_arg(1, 2, &argc, &argv, lp_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (argc == 1) { + char *str; + if (hci_read_link_policy(dd, htobs(cr->conn_info->handle), + &policy, 1000) < 0) { + perror("HCI read_link_policy_settings request failed"); + exit(1); + } + + policy = btohs(policy); + str = hci_lptostr(policy); + if (str) { + printf("Link policy settings: %s\n", str); + bt_free(str); + } else { + fprintf(stderr, "Invalig settings\n"); + exit(1); + } + } else { + unsigned int val; + if (hci_strtolp(argv[1], &val) < 0) { + fprintf(stderr, "Invalig arguments\n"); + exit(1); + } + policy = val; + + if (hci_write_link_policy(dd, htobs(cr->conn_info->handle), + htobs(policy), 1000) < 0) { + perror("HCI write_link_policy_settings request failed"); + exit(1); + } + } + + free(cr); + + hci_close_dev(dd); +} + +/* Get/Set link supervision timeout */ + +static struct option lst_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *lst_help = + "Usage:\n" + "\tlst [new value in slots]\n"; + +static void cmd_lst(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint16_t timeout; + int opt, dd; + + for_each_opt(opt, lst_options, NULL) { + switch (opt) { + default: + printf("%s", lst_help); + return; + } + } + helper_arg(1, 2, &argc, &argv, lst_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (argc == 1) { + if (hci_read_link_supervision_timeout(dd, htobs(cr->conn_info->handle), + &timeout, 1000) < 0) { + perror("HCI read_link_supervision_timeout request failed"); + exit(1); + } + + timeout = btohs(timeout); + + if (timeout) + printf("Link supervision timeout: %u slots (%.2f msec)\n", + timeout, (float) timeout * 0.625); + else + printf("Link supervision timeout never expires\n"); + } else { + timeout = strtol(argv[1], NULL, 10); + + if (hci_write_link_supervision_timeout(dd, htobs(cr->conn_info->handle), + htobs(timeout), 1000) < 0) { + perror("HCI write_link_supervision_timeout request failed"); + exit(1); + } + } + + free(cr); + + hci_close_dev(dd); +} + +/* Request authentication */ + +static struct option auth_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *auth_help = + "Usage:\n" + "\tauth \n"; + +static void cmd_auth(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + int opt, dd; + + for_each_opt(opt, auth_options, NULL) { + switch (opt) { + default: + printf("%s", auth_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, auth_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (hci_authenticate_link(dd, htobs(cr->conn_info->handle), 25000) < 0) { + perror("HCI authentication request failed"); + exit(1); + } + + free(cr); + + hci_close_dev(dd); +} + +/* Activate encryption */ + +static struct option enc_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *enc_help = + "Usage:\n" + "\tenc [encrypt enable]\n"; + +static void cmd_enc(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint8_t encrypt; + int opt, dd; + + for_each_opt(opt, enc_options, NULL) { + switch (opt) { + default: + printf("%s", enc_help); + return; + } + } + helper_arg(1, 2, &argc, &argv, enc_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + encrypt = (argc > 1) ? atoi(argv[1]) : 1; + + if (hci_encrypt_link(dd, htobs(cr->conn_info->handle), encrypt, 25000) < 0) { + perror("HCI set encryption request failed"); + exit(1); + } + + free(cr); + + hci_close_dev(dd); +} + +/* Change connection link key */ + +static struct option key_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *key_help = + "Usage:\n" + "\tkey \n"; + +static void cmd_key(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + int opt, dd; + + for_each_opt(opt, key_options, NULL) { + switch (opt) { + default: + printf("%s", key_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, key_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (hci_change_link_key(dd, htobs(cr->conn_info->handle), 25000) < 0) { + perror("Changing link key failed"); + exit(1); + } + + free(cr); + + hci_close_dev(dd); +} + +/* Read clock offset */ + +static struct option clkoff_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *clkoff_help = + "Usage:\n" + "\tclkoff \n"; + +static void cmd_clkoff(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint16_t offset; + int opt, dd; + + for_each_opt(opt, clkoff_options, NULL) { + switch (opt) { + default: + printf("%s", clkoff_help); + return; + } + } + helper_arg(1, 1, &argc, &argv, clkoff_help); + + str2ba(argv[0], &bdaddr); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + exit(1); + } + + if (hci_read_clock_offset(dd, htobs(cr->conn_info->handle), &offset, 1000) < 0) { + perror("Reading clock offset failed"); + exit(1); + } + + printf("Clock offset: 0x%4.4x\n", btohs(offset)); + + free(cr); + + hci_close_dev(dd); +} + +/* Read clock */ + +static struct option clock_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *clock_help = + "Usage:\n" + "\tclock [bdaddr] [which clock]\n"; + +static void cmd_clock(int dev_id, int argc, char **argv) +{ + struct hci_conn_info_req *cr; + bdaddr_t bdaddr; + uint8_t which; + uint32_t handle, clock; + uint16_t accuracy; + int opt, dd; + + for_each_opt(opt, clock_options, NULL) { + switch (opt) { + default: + printf("%s", clock_help); + return; + } + } + helper_arg(0, 2, &argc, &argv, clock_help); + + if (argc > 0) + str2ba(argv[0], &bdaddr); + else + bacpy(&bdaddr, BDADDR_ANY); + + if (dev_id < 0 && !bacmp(&bdaddr, BDADDR_ANY)) + dev_id = hci_get_route(NULL); + + if (dev_id < 0) { + dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); + if (dev_id < 0) { + fprintf(stderr, "Not connected.\n"); + exit(1); + } + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("HCI device open failed"); + exit(1); + } + + if (bacmp(&bdaddr, BDADDR_ANY)) { + cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) { + perror("Can't allocate memory"); + exit(1); + } + + bacpy(&cr->bdaddr, &bdaddr); + cr->type = ACL_LINK; + if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { + perror("Get connection info failed"); + free(cr); + exit(1); + } + + handle = htobs(cr->conn_info->handle); + which = (argc > 1) ? atoi(argv[1]) : 0x01; + + free(cr); + } else { + handle = 0x00; + which = 0x00; + } + + if (hci_read_clock(dd, handle, which, &clock, &accuracy, 1000) < 0) { + perror("Reading clock failed"); + exit(1); + } + + accuracy = btohs(accuracy); + + printf("Clock: 0x%4.4x\n", btohl(clock)); + printf("Accuracy: %.2f msec\n", (float) accuracy * 0.3125); + + hci_close_dev(dd); +} + +static int read_flags(uint8_t *flags, const uint8_t *data, size_t size) +{ + size_t offset; + + if (!flags || !data) + return -EINVAL; + + offset = 0; + while (offset < size) { + uint8_t len = data[offset]; + uint8_t type; + + /* Check if it is the end of the significant part */ + if (len == 0) + break; + + if (len + offset > size) + break; + + type = data[offset + 1]; + + if (type == FLAGS_AD_TYPE) { + *flags = data[offset + 2]; + return 0; + } + + offset += 1 + len; + } + + return -ENOENT; +} + +static int check_report_filter(uint8_t procedure, le_advertising_info *info) +{ + uint8_t flags; + + /* If no discovery procedure is set, all reports are treat as valid */ + if (procedure == 0) + return 1; + + /* Read flags AD type value from the advertising report if it exists */ + if (read_flags(&flags, info->data, info->length)) + return 0; + + switch (procedure) { + case 'l': /* Limited Discovery Procedure */ + if (flags & FLAGS_LIMITED_MODE_BIT) + return 1; + break; + case 'g': /* General Discovery Procedure */ + if (flags & (FLAGS_LIMITED_MODE_BIT | FLAGS_GENERAL_MODE_BIT)) + return 1; + break; + default: + fprintf(stderr, "Unknown discovery procedure\n"); + } + + return 0; +} + +static void sigint_handler(int sig) +{ + signal_received = sig; +} + +static void eir_parse_name(uint8_t *eir, size_t eir_len, + char *buf, size_t buf_len) +{ + size_t offset; + + offset = 0; + while (offset < eir_len) { + uint8_t field_len = eir[0]; + size_t name_len; + + /* Check for the end of EIR */ + if (field_len == 0) + break; + + if (offset + field_len > eir_len) + goto failed; + + switch (eir[1]) { + case EIR_NAME_SHORT: + case EIR_NAME_COMPLETE: + name_len = field_len - 1; + if (name_len > buf_len) + goto failed; + + memcpy(buf, &eir[2], name_len); + return; + } + + offset += field_len + 1; + eir += field_len + 1; + } + +failed: + snprintf(buf, buf_len, "(unknown)"); +} + +static int print_advertising_devices(int dd, uint8_t filter_type) +{ + unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr; + struct hci_filter nf, of; + struct sigaction sa; + socklen_t olen; + int len; + + olen = sizeof(of); + if (getsockopt(dd, SOL_HCI, HCI_FILTER, &of, &olen) < 0) { + printf("Could not get socket options\n"); + return -1; + } + + hci_filter_clear(&nf); + hci_filter_set_ptype(HCI_EVENT_PKT, &nf); + hci_filter_set_event(EVT_LE_META_EVENT, &nf); + + if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { + printf("Could not set socket options\n"); + return -1; + } + + memset(&sa, 0, sizeof(sa)); + sa.sa_flags = SA_NOCLDSTOP; + sa.sa_handler = sigint_handler; + sigaction(SIGINT, &sa, NULL); + + while (1) { + evt_le_meta_event *meta; + le_advertising_info *info; + char addr[18]; + + while ((len = read(dd, buf, sizeof(buf))) < 0) { + if (errno == EINTR && signal_received == SIGINT) { + len = 0; + goto done; + } + + if (errno == EAGAIN || errno == EINTR) + continue; + goto done; + } + + ptr = buf + (1 + HCI_EVENT_HDR_SIZE); + len -= (1 + HCI_EVENT_HDR_SIZE); + + meta = (void *) ptr; + + if (meta->subevent != 0x02) + goto done; + + /* Ignoring multiple reports */ + info = (le_advertising_info *) (meta->data + 1); + if (check_report_filter(filter_type, info)) { + char name[30]; + + memset(name, 0, sizeof(name)); + + ba2str(&info->bdaddr, addr); + eir_parse_name(info->data, info->length, + name, sizeof(name) - 1); + + printf("%s %s\n", addr, name); + } + } + +done: + setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of)); + + if (len < 0) + return -1; + + return 0; +} + +static struct option lescan_options[] = { + { "help", 0, 0, 'h' }, + { "privacy", 0, 0, 'p' }, + { "passive", 0, 0, 'P' }, + { "whitelist", 0, 0, 'w' }, + { "discovery", 1, 0, 'd' }, + { "duplicates", 0, 0, 'D' }, + { 0, 0, 0, 0 } +}; + +static const char *lescan_help = + "Usage:\n" + "\tlescan [--privacy] enable privacy\n" + "\tlescan [--passive] set scan type passive (default active)\n" + "\tlescan [--whitelist] scan for address in the whitelist only\n" + "\tlescan [--discovery=g|l] enable general or limited discovery" + "procedure\n" + "\tlescan [--duplicates] don't filter duplicates\n"; + +static void cmd_lescan(int dev_id, int argc, char **argv) +{ + int err, opt, dd; + uint8_t own_type = 0x00; + uint8_t scan_type = 0x01; + uint8_t filter_type = 0; + uint8_t filter_policy = 0x00; + uint16_t interval = htobs(0x0010); + uint16_t window = htobs(0x0010); + uint8_t filter_dup = 1; + + for_each_opt(opt, lescan_options, NULL) { + switch (opt) { + case 'p': + own_type = 0x01; /* Random */ + break; + case 'P': + scan_type = 0x00; /* Passive */ + break; + case 'w': + filter_policy = 0x01; /* Whitelist */ + break; + case 'd': + filter_type = optarg[0]; + if (filter_type != 'g' && filter_type != 'l') { + fprintf(stderr, "Unknown discovery procedure\n"); + exit(1); + } + + interval = htobs(0x0012); + window = htobs(0x0012); + break; + case 'D': + filter_dup = 0x00; + break; + default: + printf("%s", lescan_help); + return; + } + } + helper_arg(0, 1, &argc, &argv, lescan_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + err = hci_le_set_scan_parameters(dd, scan_type, interval, window, + own_type, filter_policy, 1000); + if (err < 0) { + perror("Set scan parameters failed"); + exit(1); + } + + err = hci_le_set_scan_enable(dd, 0x01, filter_dup, 1000); + if (err < 0) { + perror("Enable scan failed"); + exit(1); + } + + printf("LE Scan ...\n"); + + err = print_advertising_devices(dd, filter_type); + if (err < 0) { + perror("Could not receive advertising events"); + exit(1); + } + + err = hci_le_set_scan_enable(dd, 0x00, filter_dup, 1000); + if (err < 0) { + perror("Disable scan failed"); + exit(1); + } + + hci_close_dev(dd); +} + +static struct option lecc_options[] = { + { "help", 0, 0, 'h' }, + { "random", 0, 0, 'r' }, + { "whitelist", 0, 0, 'w' }, + { 0, 0, 0, 0 } +}; + +static const char *lecc_help = + "Usage:\n" + "\tlecc [--random] \n" + "\tlecc --whitelist\n"; + +static void cmd_lecc(int dev_id, int argc, char **argv) +{ + int err, opt, dd; + bdaddr_t bdaddr; + uint16_t interval, latency, max_ce_length, max_interval, min_ce_length; + uint16_t min_interval, supervision_timeout, window, handle; + uint8_t initiator_filter, own_bdaddr_type, peer_bdaddr_type; + + peer_bdaddr_type = LE_PUBLIC_ADDRESS; + initiator_filter = 0; /* Use peer address */ + + for_each_opt(opt, lecc_options, NULL) { + switch (opt) { + case 'r': + peer_bdaddr_type = LE_RANDOM_ADDRESS; + break; + case 'w': + initiator_filter = 0x01; /* Use white list */ + break; + default: + printf("%s", lecc_help); + return; + } + } + helper_arg(0, 1, &argc, &argv, lecc_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + memset(&bdaddr, 0, sizeof(bdaddr_t)); + if (argv[0]) + str2ba(argv[0], &bdaddr); + + interval = htobs(0x0004); + window = htobs(0x0004); + own_bdaddr_type = 0x00; + min_interval = htobs(0x000F); + max_interval = htobs(0x000F); + latency = htobs(0x0000); + supervision_timeout = htobs(0x0C80); + min_ce_length = htobs(0x0001); + max_ce_length = htobs(0x0001); + + err = hci_le_create_conn(dd, interval, window, initiator_filter, + peer_bdaddr_type, bdaddr, own_bdaddr_type, min_interval, + max_interval, latency, supervision_timeout, + min_ce_length, max_ce_length, &handle, 25000); + if (err < 0) { + perror("Could not create connection"); + exit(1); + } + + printf("Connection handle %d\n", handle); + + hci_close_dev(dd); +} + +static struct option lewladd_options[] = { + { "help", 0, 0, 'h' }, + { "random", 0, 0, 'r' }, + { 0, 0, 0, 0 } +}; + +static const char *lewladd_help = + "Usage:\n" + "\tlewladd [--random] \n"; + +static void cmd_lewladd(int dev_id, int argc, char **argv) +{ + int err, opt, dd; + bdaddr_t bdaddr; + uint8_t bdaddr_type = LE_PUBLIC_ADDRESS; + + for_each_opt(opt, lewladd_options, NULL) { + switch (opt) { + case 'r': + bdaddr_type = LE_RANDOM_ADDRESS; + break; + default: + printf("%s", lewladd_help); + return; + } + } + + helper_arg(1, 1, &argc, &argv, lewladd_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + str2ba(argv[0], &bdaddr); + + err = hci_le_add_white_list(dd, &bdaddr, bdaddr_type, 1000); + hci_close_dev(dd); + + if (err < 0) { + err = -errno; + fprintf(stderr, "Can't add to white list: %s(%d)\n", + strerror(-err), -err); + exit(1); + } +} + +static struct option lewlrm_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *lewlrm_help = + "Usage:\n" + "\tlewlrm \n"; + +static void cmd_lewlrm(int dev_id, int argc, char **argv) +{ + int err, opt, dd; + bdaddr_t bdaddr; + + for_each_opt(opt, lewlrm_options, NULL) { + switch (opt) { + default: + printf("%s", lewlrm_help); + return; + } + } + + helper_arg(1, 1, &argc, &argv, lewlrm_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + str2ba(argv[0], &bdaddr); + + err = hci_le_rm_white_list(dd, &bdaddr, LE_PUBLIC_ADDRESS, 1000); + hci_close_dev(dd); + + if (err < 0) { + err = errno; + fprintf(stderr, "Can't remove from white list: %s(%d)\n", + strerror(err), err); + exit(1); + } +} + +static struct option lewlsz_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *lewlsz_help = + "Usage:\n" + "\tlewlsz\n"; + +static void cmd_lewlsz(int dev_id, int argc, char **argv) +{ + int err, dd, opt; + uint8_t size; + + for_each_opt(opt, lewlsz_options, NULL) { + switch (opt) { + default: + printf("%s", lewlsz_help); + return; + } + } + + helper_arg(0, 0, &argc, &argv, lewlsz_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + err = hci_le_read_white_list_size(dd, &size, 1000); + hci_close_dev(dd); + + if (err < 0) { + err = -errno; + fprintf(stderr, "Can't read white list size: %s(%d)\n", + strerror(-err), -err); + exit(1); + } + + printf("White list size: %d\n", size); +} + +static struct option lewlclr_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *lewlclr_help = + "Usage:\n" + "\tlewlclr\n"; + +static void cmd_lewlclr(int dev_id, int argc, char **argv) +{ + int err, dd, opt; + + for_each_opt(opt, lewlclr_options, NULL) { + switch (opt) { + default: + printf("%s", lewlclr_help); + return; + } + } + + helper_arg(0, 0, &argc, &argv, lewlclr_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + err = hci_le_clear_white_list(dd, 1000); + hci_close_dev(dd); + + if (err < 0) { + err = -errno; + fprintf(stderr, "Can't clear white list: %s(%d)\n", + strerror(-err), -err); + exit(1); + } +} + +static struct option ledc_options[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static const char *ledc_help = + "Usage:\n" + "\tledc [reason]\n"; + +static void cmd_ledc(int dev_id, int argc, char **argv) +{ + int err, opt, dd; + uint16_t handle; + uint8_t reason; + + for_each_opt(opt, ledc_options, NULL) { + switch (opt) { + default: + printf("%s", ledc_help); + return; + } + } + helper_arg(1, 2, &argc, &argv, ledc_help); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("Could not open device"); + exit(1); + } + + handle = atoi(argv[0]); + + reason = (argc > 1) ? atoi(argv[1]) : HCI_OE_USER_ENDED_CONNECTION; + + err = hci_disconnect(dd, handle, reason, 10000); + if (err < 0) { + perror("Could not disconnect"); + exit(1); + } + + hci_close_dev(dd); +} + +static struct option lecup_options[] = { + { "help", 0, 0, 'h' }, + { "handle", 1, 0, 'H' }, + { "min", 1, 0, 'm' }, + { "max", 1, 0, 'M' }, + { "latency", 1, 0, 'l' }, + { "timeout", 1, 0, 't' }, + { 0, 0, 0, 0 } +}; + +static const char *lecup_help = + "Usage:\n" + "\tlecup \n" + "\tOptions:\n" + "\t -H, --handle <0xXXXX> LE connection handle\n" + "\t -m, --min Range: 0x0006 to 0x0C80\n" + "\t -M, --max Range: 0x0006 to 0x0C80\n" + "\t -l, --latency Slave latency. Range: 0x0000 to 0x03E8\n" + "\t -t, --timeout