mirror of
https://github.com/riptidewave93/UNVR-NAS.git
synced 2025-02-12 10:31:55 +00:00
feat: initial bluetooth support (#9)
* Enable Bluetooth LE radio support * Build our own bccmd which we need to setup/enable this BT chipset sadly * Use our own tool we build to interface with the ubnt eeprom, so we can not rely on their custom kernel module * Also fix HDDs not spinning down on shutdown, doing something similar to how unifi does it but a tad more generic.
This commit is contained in:
parent
fe3b4cd76f
commit
9ef1a72228
15 changed files with 678 additions and 20 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,4 +2,5 @@
|
||||||
unifi-firmware/*.bin
|
unifi-firmware/*.bin
|
||||||
BuildEnv
|
BuildEnv
|
||||||
output
|
output
|
||||||
downloads
|
downloads
|
||||||
|
tools/ubnteeprom/test-files
|
15
Dockerfile
15
Dockerfile
|
@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -yq \
|
||||||
bsdextrautils \
|
bsdextrautils \
|
||||||
build-essential \
|
build-essential \
|
||||||
cpio \
|
cpio \
|
||||||
|
curl \
|
||||||
debootstrap \
|
debootstrap \
|
||||||
debhelper \
|
debhelper \
|
||||||
device-tree-compiler \
|
device-tree-compiler \
|
||||||
|
@ -26,9 +27,14 @@ RUN apt-get update && apt-get install -yq \
|
||||||
kpartx \
|
kpartx \
|
||||||
libconfuse-common \
|
libconfuse-common \
|
||||||
libconfuse-dev \
|
libconfuse-dev \
|
||||||
|
libdbus-1-dev \
|
||||||
libelf-dev \
|
libelf-dev \
|
||||||
|
libglib2.0-dev \
|
||||||
|
libical-dev \
|
||||||
libncurses-dev \
|
libncurses-dev \
|
||||||
|
libreadline-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
|
libudev-dev \
|
||||||
lvm2 \
|
lvm2 \
|
||||||
mtools \
|
mtools \
|
||||||
parted \
|
parted \
|
||||||
|
@ -47,4 +53,11 @@ RUN apt-get update && apt-get install -yq \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& /setup_mkimage.sh \
|
&& /setup_mkimage.sh \
|
||||||
&& rm /setup_mkimage.sh
|
&& rm /setup_mkimage.sh \
|
||||||
|
&& curl -fsSL "https://go.dev/dl/go1.22.4.linux-amd64.tar.gz" -o golang.tar.gz \
|
||||||
|
&& tar -C /usr/local -xzf golang.tar.gz \
|
||||||
|
&& rm golang.tar.gz \
|
||||||
|
&& for bin in `ls /usr/local/go/bin/`; do \
|
||||||
|
update-alternatives --install "/usr/bin/$bin" "$bin" "/usr/local/go/bin/$bin" 1; \
|
||||||
|
update-alternatives --set "$bin" "/usr/local/go/bin/$bin"; \
|
||||||
|
done
|
|
@ -4,7 +4,8 @@ Description=UBNT bootup init script
|
||||||
[Service]
|
[Service]
|
||||||
User=root
|
User=root
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
ExecStart=/usr/lib/init/boot/ubnt-init.sh
|
ExecStart=/usr/lib/init/boot/ubnt-init.sh start
|
||||||
|
ExecStop=/usr/lib/init/boot/ubnt-init.sh stop
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ "$1" == "id" ]; then
|
if [ "$1" == "id" ]; then
|
||||||
BOARD_SYSID=$(grep systemid /proc/ubnthal/system.info | sed 's|systemid=||g')
|
ubnteeprom -tools
|
||||||
BOARD_SERIALNO=$(grep serialno /proc/ubnthal/system.info | sed 's|serialno=||g')
|
|
||||||
# BOM is in SPI on EEPROM part, offset D000 is start of TlvInfo. BOM starts with 113-
|
|
||||||
BOARD_BOM=$(dd if=/dev/mtd4 bs=64 skip=832 count=1 status=none | strings | grep 113-)
|
|
||||||
echo "board.sysid=0x${BOARD_SYSID}"
|
|
||||||
echo "board.serialno=${BOARD_SERIALNO}"
|
|
||||||
echo "board.bom=${BOARD_BOM}"
|
|
||||||
else
|
else
|
||||||
echo "Unknown ubnt-tools cmd: $@" >> /tmp/ubnt-tools-unknown.log
|
echo "Unknown ubnt-tools cmd: $@" >> /tmp/ubnt-tools-unknown.log
|
||||||
fi
|
fi
|
||||||
|
|
178
overlay/filesystem/usr/lib/init/boot/ubnt-bt.sh
Executable file
178
overlay/filesystem/usr/lib/init/boot/ubnt-bt.sh
Executable file
|
@ -0,0 +1,178 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
echo "<3> ${*}" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_bt_mac() {
|
||||||
|
local bt_device_num="$1"
|
||||||
|
if [ -z "${bt_device_num}" ]; then
|
||||||
|
log_error "get_bt_mac: Unknown device num"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local hw_addr_base=$(ubnteeprom -board -key "hwaddrbbase")
|
||||||
|
local eth_count=$(ubnteeprom -board -key "EthMACAddrCount")
|
||||||
|
local wifi_count=$(ubnteeprom -board -key "WiFiMACAddrCount")
|
||||||
|
local bt_count=$(ubnteeprom -board -key "BtMACAddrCount")
|
||||||
|
|
||||||
|
if [ -z "${hw_addr_base}" ] || [ -z "${eth_count}" ] || [ -z "${wifi_count}" ] || [ -z "${bt_count}" ]; then
|
||||||
|
log_error "Unexpected contents in $UBNTHAL_BOARD"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${bt_device_num} -ge ${bt_count} ]; then
|
||||||
|
log_error "Unsupported device number (bt_device_num[${bt_device_num}] >= bt_count[${bt_count}])"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
local mac=$(echo "${hw_addr_base}" | sed s/":"//g)
|
||||||
|
local mac_dec=$(printf '%d\n' 0x${mac})
|
||||||
|
local bt_mac_dec=$(expr ${mac_dec} + ${eth_count} + ${wifi_count} + ${bt_device_num})
|
||||||
|
|
||||||
|
printf '%012X\n' "${bt_mac_dec}" | tr A-Z a-z
|
||||||
|
}
|
||||||
|
|
||||||
|
function main(){
|
||||||
|
BT_DEVICE="$1"
|
||||||
|
[ -z "$BT_DEVICE" ] && return 2
|
||||||
|
|
||||||
|
BT_DEVICE_NUM=$(echo "${BT_DEVICE}" | sed s/"hci"//g)
|
||||||
|
if [[ ! "${BT_DEVICE_NUM}" =~ ^[0-9]+$ ]]; then
|
||||||
|
log_error "Invalid bluetooth device number [${BT_DEVICE_NUM}]"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
BT_MAC=$(get_bt_mac "${BT_DEVICE_NUM}")
|
||||||
|
[ $? -eq 0 ] || return 4
|
||||||
|
|
||||||
|
local board_id=$(ubnteeprom -board -key "boardid")
|
||||||
|
case ${board_id} in
|
||||||
|
ea16)
|
||||||
|
# unvr: nothing to do here
|
||||||
|
;;
|
||||||
|
ea1a)
|
||||||
|
usb_based_init
|
||||||
|
;;
|
||||||
|
ea20|ea50|ea51)
|
||||||
|
gpio_num=$(find_gpio_on_expander 0 0020 8)
|
||||||
|
if [ $gpio_num -lt 0 ]; then
|
||||||
|
return 5
|
||||||
|
fi
|
||||||
|
gpio_reset $gpio_num
|
||||||
|
uart_based_init /dev/ttyS3 "/lib/firmware/csr8x11/csr8x11-a12-bt4.2-patch-2018_uart.psr"
|
||||||
|
;;
|
||||||
|
ea2c|ea15|ea11|ea32)
|
||||||
|
gpio_reset 37
|
||||||
|
uart_based_init /dev/ttyS1 "/lib/firmware/csr8x11/csr8x11-a12-bt4.2-patch-2018_uart.psr"
|
||||||
|
;;
|
||||||
|
ea3d|ea3e)
|
||||||
|
gpio_num=$(find_gpio_on_expander 3 0029 13)
|
||||||
|
if [ $gpio_num -lt 0 ]; then
|
||||||
|
return 5
|
||||||
|
fi
|
||||||
|
gpio_reset $gpio_num
|
||||||
|
uart_based_init /dev/ttyAMA1 "/lib/firmware/csr8x11/pb-207-csr8x11-rev7-flowcontrol.psr" "flow"
|
||||||
|
;;
|
||||||
|
a678|a690|a69a)
|
||||||
|
gpio_reset 490
|
||||||
|
usb_based_init
|
||||||
|
;;
|
||||||
|
e990)
|
||||||
|
gpio_reset 306
|
||||||
|
usb_based_init
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 4
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function find_gpio_on_expander() {
|
||||||
|
local bus=$1
|
||||||
|
local addr=$2
|
||||||
|
local pin=$3
|
||||||
|
local gpiochip_dir="/sys/bus/i2c/devices/$bus-$addr/gpio"
|
||||||
|
local base
|
||||||
|
|
||||||
|
for chip in $(find $gpiochip_dir -maxdepth 1 -name 'gpiochip*' -printf "%f\n"); do
|
||||||
|
base=$(echo $chip | sed 's/gpiochip//g')
|
||||||
|
echo $((base + pin))
|
||||||
|
return
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -1
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpio_reset(){
|
||||||
|
local gpio=$1
|
||||||
|
|
||||||
|
if [ ! -d /sys/class/gpio/gpio${gpio} ]; then
|
||||||
|
echo ${gpio} > /sys/class/gpio/export
|
||||||
|
fi
|
||||||
|
echo out > /sys/class/gpio/gpio${gpio}/direction
|
||||||
|
echo 1 > /sys/class/gpio/gpio${gpio}/value
|
||||||
|
sleep 1
|
||||||
|
echo 0 > /sys/class/gpio/gpio${gpio}/value
|
||||||
|
sleep 1
|
||||||
|
echo 1 > /sys/class/gpio/gpio${gpio}/value
|
||||||
|
sleep 1
|
||||||
|
echo ${gpio} > /sys/class/gpio/unexport
|
||||||
|
}
|
||||||
|
|
||||||
|
function uart_based_init(){
|
||||||
|
local bt_serial_dev="$1"
|
||||||
|
local bt_serial_speed="115200"
|
||||||
|
local bt_fw="$2"
|
||||||
|
local bt_option="$3"
|
||||||
|
local bt_proto="bcsp"
|
||||||
|
local loop_no=10
|
||||||
|
local i=0
|
||||||
|
|
||||||
|
for i in $(seq 0 ${loop_no}); do
|
||||||
|
if [ ${i} -gt 0 ]; then
|
||||||
|
if [ ${i} -eq ${loop_no} ]; then
|
||||||
|
log_error "Failed to initialize bluetooth (BT is not operational)"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
log_error "Unable to initialize bluetooth. Give it another try (${i})"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#load psr file
|
||||||
|
bccmd -t "${bt_proto}" -b "${bt_serial_speed}" -d "${bt_serial_dev}" psload -r ${bt_fw} || continue
|
||||||
|
|
||||||
|
#set bt address: <device index> <mac byte 4> 0x00 <mac byte 6> <mac byte 5> <mac byte 3> 0x00 <mac byte 2> <mac byte 1>
|
||||||
|
bccmd -t "${bt_proto}" -d "${bt_serial_dev}" -b "${bt_serial_speed}" psset -r \
|
||||||
|
0x$((BT_DEVICE_NUM+1)) \
|
||||||
|
0x${BT_MAC:6:2} \
|
||||||
|
0x00 \
|
||||||
|
0x${BT_MAC:10:2} \
|
||||||
|
0x${BT_MAC:8:2} \
|
||||||
|
0x${BT_MAC:4:2} \
|
||||||
|
0x00 \
|
||||||
|
0x${BT_MAC:2:2} \
|
||||||
|
0x${BT_MAC:0:2} \
|
||||||
|
2>&1
|
||||||
|
|
||||||
|
# attach UART interface
|
||||||
|
hciattach -s "${bt_serial_speed}" "${bt_serial_dev}" "${bt_proto}" "${bt_serial_speed}" "${bt_option}"
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
|
# check if the device exists
|
||||||
|
[ -d "/sys/class/bluetooth/${BT_DEVICE}" ] && break
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
hciconfig ${BT_DEVICE} up
|
||||||
|
}
|
||||||
|
|
||||||
|
function usb_based_init(){
|
||||||
|
hciconfig ${BT_DEVICE} up; hciconfig ${BT_DEVICE} up
|
||||||
|
sleep 1
|
||||||
|
bccmd psset -r 0x$((BT_DEVICE_NUM+1)) 0x${BT_MAC:6:2} 00 0x${BT_MAC:10:2} 0x${BT_MAC:8:2} 0x${BT_MAC:4:2} 00 0x${BT_MAC:2:2} 0x${BT_MAC:0:2}
|
||||||
|
sleep 2
|
||||||
|
hciconfig ${BT_DEVICE} down
|
||||||
|
hciconfig ${BT_DEVICE} up; hciconfig ${BT_DEVICE} up
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
|
@ -1,8 +1,22 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Load our kernel modules
|
case "$1" in
|
||||||
/usr/sbin/modprobe ubnthal
|
start)
|
||||||
/usr/sbin/modprobe btrfs
|
# Load our kernel modules
|
||||||
|
/usr/sbin/modprobe ubnthal
|
||||||
|
/usr/sbin/modprobe btrfs
|
||||||
|
|
||||||
# Set our kernel panic timeout SUPER short so we reboot on crash
|
# Set our kernel panic timeout SUPER short so we reboot on crash
|
||||||
echo 2 > /proc/sys/kernel/panic
|
echo 2 > /proc/sys/kernel/panic
|
||||||
|
|
||||||
|
# Setup bluetooth hci0 device
|
||||||
|
/usr/lib/init/boot/ubnt-bt.sh hci0
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
# Tear down BT
|
||||||
|
hciconfig hci0 down
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid command $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
29
overlay/filesystem/usr/lib/systemd/system-shutdown/unifi-shutdown
Executable file
29
overlay/filesystem/usr/lib/systemd/system-shutdown/unifi-shutdown
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# turn off fans for shutdown
|
||||||
|
if [ -d "/sys/class/hwmon/hwmon0/device" ]; then
|
||||||
|
for pwm in `ls /sys/class/hwmon/hwmon0/device/pwm[0-6]`; do
|
||||||
|
echo 0 > ${pwm}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure all mounts in /srv from OMV are cleaned up
|
||||||
|
for dir in `ls /srv | grep dev-disk`; do
|
||||||
|
umount -q /srv/${dir};
|
||||||
|
done
|
||||||
|
|
||||||
|
# Now for all disks, delete from bus
|
||||||
|
for dsk in sd{a..z}; do
|
||||||
|
if [ -d "/sys/block/${dsk}/device" ]; then
|
||||||
|
echo 1 > "/sys/block/${dsk}/device/delete"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Now for all disks, remove them with ui-hdd-pwrctl-v2 if we have it
|
||||||
|
if [ -d "/sys/bus/platform/drivers/ui-hdd-pwrctl-v2" ]; then
|
||||||
|
for bay in `seq 0 7`; do
|
||||||
|
echo ${bay} > "$(realpath /sys/bus/platform/drivers/ui-hdd-pwrctl-v2/*hdd_pwrctl-v2)/hdd_force_poweroff"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
# Let the disks spool down a sec...
|
||||||
|
sleep 2
|
|
@ -24,4 +24,10 @@ if [ ! -f ${root_path}/downloads/${kernel_filename} ]; then
|
||||||
wget ${kernel_src} -O ${root_path}/downloads/${kernel_filename}
|
wget ${kernel_src} -O ${root_path}/downloads/${kernel_filename}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Bluez
|
||||||
|
if [ ! -f ${root_path}/downloads/${bluez_filename} ]; then
|
||||||
|
debug_msg "Downloading Package Bluez..."
|
||||||
|
wget ${bluez_src} -O ${root_path}/downloads/${bluez_filename}
|
||||||
|
fi
|
||||||
|
|
||||||
debug_msg "Finished 02_download_dependencies.sh"
|
debug_msg "Finished 02_download_dependencies.sh"
|
||||||
|
|
|
@ -18,6 +18,10 @@ if [ ! -d ${build_path}/kernel ]; then
|
||||||
debug_msg "Docker: Building Kernel..."
|
debug_msg "Docker: Building Kernel..."
|
||||||
docker run --ulimit nofile=1024 --rm -v "${root_path}:/repo:Z" -it ${docker_tag} /repo/scripts/docker/build_kernel.sh
|
docker run --ulimit nofile=1024 --rm -v "${root_path}:/repo:Z" -it ${docker_tag} /repo/scripts/docker/build_kernel.sh
|
||||||
fi
|
fi
|
||||||
|
if [ ! -d ${build_path}/packages ]; then
|
||||||
|
debug_msg "Docker: Building Packages..."
|
||||||
|
docker run --ulimit nofile=1024 --rm -v "${root_path}:/repo:Z" -it ${docker_tag} /repo/scripts/docker/build_packages.sh
|
||||||
|
fi
|
||||||
|
|
||||||
debug_msg "Doing safety checks... please enter your password for sudo if prompted..."
|
debug_msg "Doing safety checks... please enter your password for sudo if prompted..."
|
||||||
# Before we do anything, make our dirs, and validate they are not mounted atm. If they are, exit!
|
# Before we do anything, make our dirs, and validate they are not mounted atm. If they are, exit!
|
||||||
|
|
|
@ -32,7 +32,10 @@ apt-get -o Dpkg::Options::="--force-confold" -y --allow-downgrades \
|
||||||
bsdextrautils git binutils ca-certificates e2fsprogs haveged parted curl \
|
bsdextrautils git binutils ca-certificates e2fsprogs haveged parted curl \
|
||||||
locales console-common openssh-server less vim net-tools wireguard-tools \
|
locales console-common openssh-server less vim net-tools wireguard-tools \
|
||||||
ntpsec u-boot-tools wget initramfs-tools python3-flask gnupg libc-ares2 \
|
ntpsec u-boot-tools wget initramfs-tools python3-flask gnupg libc-ares2 \
|
||||||
dfu-util
|
dfu-util bluez
|
||||||
|
|
||||||
|
# Enable bluetooth
|
||||||
|
systemctl enable bluetooth
|
||||||
|
|
||||||
# Locale gen
|
# Locale gen
|
||||||
locale-gen
|
locale-gen
|
||||||
|
|
|
@ -37,9 +37,9 @@ fi
|
||||||
# some modules. This is why some lines below are commented out.
|
# some modules. This is why some lines below are commented out.
|
||||||
|
|
||||||
# Build as normal, with our extra version set to a timestamp
|
# Build as normal, with our extra version set to a timestamp
|
||||||
make ${kernel_config}
|
make ${kernel_config}
|
||||||
make -j`getconf _NPROCESSORS_ONLN` EXTRAVERSION=-alpine-unvr # Build kernel and modules
|
make -j`getconf _NPROCESSORS_ONLN` EXTRAVERSION=-alpine-unvr # Build kernel and modules
|
||||||
#make -j`getconf _NPROCESSORS_ONLN` EXTRAVERSION=-alpine-unvr Image.gz # makes gzip image
|
#make -j`getconf _NPROCESSORS_ONLN` EXTRAVERSION=-alpine-unvr Image.gz # makes gzip image (we should just do this ourselves, skip using make)
|
||||||
make INSTALL_MOD_PATH=./modules-dir -j`getconf _NPROCESSORS_ONLN` EXTRAVERSION=-alpine-unvr modules_install # installs modules to dir
|
make INSTALL_MOD_PATH=./modules-dir -j`getconf _NPROCESSORS_ONLN` EXTRAVERSION=-alpine-unvr modules_install # installs modules to dir
|
||||||
#mkimage -A arm64 -O linux -T kernel -C gzip -a 04080000 -e 04080000 -n "Linux-UNVR-NAS-$(date +%Y%m%d-%H%M%S)" -d ./arch/arm64/boot/Image.gz uImage
|
#mkimage -A arm64 -O linux -T kernel -C gzip -a 04080000 -e 04080000 -n "Linux-UNVR-NAS-$(date +%Y%m%d-%H%M%S)" -d ./arch/arm64/boot/Image.gz uImage
|
||||||
|
|
||||||
|
|
55
scripts/docker/build_packages.sh
Executable file
55
scripts/docker/build_packages.sh
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
scripts_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
|
||||||
|
. ${scripts_path}/vars.sh
|
||||||
|
|
||||||
|
# Exports baby
|
||||||
|
export PATH=${build_path}/toolchain/${toolchain_bin_path}:${PATH}
|
||||||
|
export GCC_COLORS=auto
|
||||||
|
export CROSS_COMPILE=${toolchain_cross_compile}
|
||||||
|
export ARCH=arm64
|
||||||
|
|
||||||
|
# Make our temp builddir for bluez so we can make bccmd
|
||||||
|
bluez_builddir=$(mktemp -d)
|
||||||
|
tar -xzf ${root_path}/downloads/${bluez_filename} -C ${bluez_builddir}
|
||||||
|
|
||||||
|
# Start with Bluez
|
||||||
|
cd ${bluez_builddir}/${bluez_repopath}
|
||||||
|
|
||||||
|
# If we have patches, apply them
|
||||||
|
if [[ -d ${root_path}/patches/bluez/ ]]; then
|
||||||
|
for file in ${root_path}/patches/bluez/*.patch; do
|
||||||
|
echo "Applying bluez patch ${file}"
|
||||||
|
patch -p1 < ${file}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build bccmd from bluez
|
||||||
|
./bootstrap
|
||||||
|
./configure --disable-systemd \
|
||||||
|
--enable-deprecated \
|
||||||
|
--disable-library \
|
||||||
|
--disable-cups \
|
||||||
|
--disable-datafiles \
|
||||||
|
--disable-manpages \
|
||||||
|
--disable-pie \
|
||||||
|
--disable-client \
|
||||||
|
--disable-obex \
|
||||||
|
--disable-udev \
|
||||||
|
--build=x86_64-linux-gnu \
|
||||||
|
--host=aarch64-none-linux-gnu \
|
||||||
|
--target=aarch64-none-linux-gnu
|
||||||
|
make lib/bluetooth/hci.h lib/bluetooth/bluetooth.h lib/libbluetooth-internal.la tools/bccmd -j`getconf _NPROCESSORS_ONLN`
|
||||||
|
|
||||||
|
# Save our binary
|
||||||
|
mkdir -p ${build_path}/packages/bluez
|
||||||
|
mv ./tools/bccmd ${build_path}/packages/bluez/
|
||||||
|
|
||||||
|
# Build ubnteeprom (our own tool)
|
||||||
|
mkdir -p ${build_path}/packages/ubnteeprom
|
||||||
|
env GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o ${build_path}/packages/ubnteeprom/ubnteeprom ${root_path}/tools/ubnteeprom/main.go
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
cd - > /dev/null
|
||||||
|
rm -rf ${bluez_builddir}
|
|
@ -35,8 +35,8 @@ if [[ -d ${root_path}/overlay/${fs_overlay_dir}/ ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Apply our part UUIDs to fstab
|
# Apply our part UUIDs to fstab
|
||||||
sed -i "s|BOOTUUIDPLACEHOLDER|$(blkid -o value -s UUID ${build_path}/boot.ext4)|g" ${build_path}/rootfs/etc/fstab
|
#sed -i "s|BOOTUUIDPLACEHOLDER|$(blkid -o value -s UUID ${build_path}/boot.ext4)|g" ${build_path}/rootfs/etc/fstab
|
||||||
sed -i "s|ROOTUUIDPLACEHOLDER|$(blkid -o value -s UUID ${build_path}/rootfs.ext4)|g" ${build_path}/rootfs/etc/fstab
|
#sed -i "s|ROOTUUIDPLACEHOLDER|$(blkid -o value -s UUID ${build_path}/rootfs.ext4)|g" ${build_path}/rootfs/etc/fstab
|
||||||
|
|
||||||
# Hostname
|
# Hostname
|
||||||
echo "${distrib_name}" > ${build_path}/rootfs/etc/hostname
|
echo "${distrib_name}" > ${build_path}/rootfs/etc/hostname
|
||||||
|
@ -56,6 +56,18 @@ for file in libgrpc++.so.1 libgrpc.so.10 libprotobuf.so.23 \
|
||||||
cp -H ${build_path}/fw-extract/rootfs/usr/lib/aarch64-linux-gnu/${file} "${build_path}/rootfs/usr/lib/ubnt-fw/"
|
cp -H ${build_path}/fw-extract/rootfs/usr/lib/aarch64-linux-gnu/${file} "${build_path}/rootfs/usr/lib/ubnt-fw/"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Copy over bluetooth firmware files
|
||||||
|
mkdir -p "${build_path}/rootfs/lib/firmware"
|
||||||
|
cp -R "${build_path}/fw-extract/rootfs/lib/firmware/csr8x11" "${build_path}/rootfs/lib/firmware/" # LCD panel firmwares
|
||||||
|
|
||||||
|
# Install our bccmd we compiled (less we use from unifi the better)
|
||||||
|
cp -R "${build_path}/packages/bluez/bccmd" "${build_path}/rootfs/usr/bin"
|
||||||
|
chmod +x "${build_path}/rootfs/usr/bin/bccmd"
|
||||||
|
|
||||||
|
# Install our ubnteeprom tool
|
||||||
|
cp -R "${build_path}/packages/ubnteeprom/ubnteeprom" "${build_path}/rootfs/usr/bin"
|
||||||
|
chmod +x "${build_path}/rootfs/usr/bin/ubnteeprom"
|
||||||
|
|
||||||
# Kick off bash setup script within chroot
|
# Kick off bash setup script within chroot
|
||||||
cp ${docker_scripts_path}/bootstrap/001-bootstrap ${build_path}/rootfs/bootstrap
|
cp ${docker_scripts_path}/bootstrap/001-bootstrap ${build_path}/rootfs/bootstrap
|
||||||
chroot ${build_path}/rootfs /bootstrap
|
chroot ${build_path}/rootfs /bootstrap
|
||||||
|
|
|
@ -27,6 +27,11 @@ genimage_src="https://github.com/pengutronix/genimage/releases/download/v16/geni
|
||||||
genimage_filename="$(basename ${genimage_src})"
|
genimage_filename="$(basename ${genimage_src})"
|
||||||
genimage_repopath="${genimage_filename%.tar.xz}"
|
genimage_repopath="${genimage_filename%.tar.xz}"
|
||||||
|
|
||||||
|
# bluez
|
||||||
|
bluez_src="https://github.com/bluez/bluez/archive/refs/tags/5.55.tar.gz"
|
||||||
|
bluez_filename="bluez-$(basename ${bluez_src})"
|
||||||
|
bluez_repopath="${bluez_filename%.tar.gz}"
|
||||||
|
|
||||||
# Distro
|
# Distro
|
||||||
distrib_name="debian"
|
distrib_name="debian"
|
||||||
#deb_mirror="http://ftp.us.debian.org/debian"
|
#deb_mirror="http://ftp.us.debian.org/debian"
|
||||||
|
|
343
tools/ubnteeprom/main.go
Normal file
343
tools/ubnteeprom/main.go
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Type for EEPROM structure
|
||||||
|
type EEPROM_Value struct {
|
||||||
|
name, description, vtype string
|
||||||
|
offset, length int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build our BOARD eeprom structure
|
||||||
|
var BOARD = []EEPROM_Value{
|
||||||
|
{
|
||||||
|
name: "format",
|
||||||
|
description: "EEPROM Format",
|
||||||
|
offset: 0x800C,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "version",
|
||||||
|
description: "EEPROM Version",
|
||||||
|
offset: 0x800E,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "boardid",
|
||||||
|
description: "Board Identifier (bomrev+model identifier)",
|
||||||
|
offset: 0x8012,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "vendorid",
|
||||||
|
description: "Vendor Identifier",
|
||||||
|
offset: 0x8010,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bomrev",
|
||||||
|
description: "Bill of Materials Revision",
|
||||||
|
offset: 0x8014,
|
||||||
|
length: 0x4,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hwaddrbbase",
|
||||||
|
description: "Base Mac Address for Device",
|
||||||
|
offset: 0x8018,
|
||||||
|
length: 0x6,
|
||||||
|
vtype: "hexmac",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "EthMACAddrCount",
|
||||||
|
description: "Number of MAC addresses for ethernet interfaces",
|
||||||
|
offset: 0x801E,
|
||||||
|
length: 0x1,
|
||||||
|
vtype: "hexint",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "WiFiMACAddrCount",
|
||||||
|
description: "Number of MAC addresses for WiFi interfaces",
|
||||||
|
offset: 0x801F,
|
||||||
|
length: 0x1,
|
||||||
|
vtype: "hexint",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BtMACAddrCount",
|
||||||
|
description: "Number of MAC addresses for Bluetooth interfaces",
|
||||||
|
offset: 0x8070,
|
||||||
|
length: 0x1,
|
||||||
|
vtype: "hexint",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[0]",
|
||||||
|
description: "Region Domain 0",
|
||||||
|
offset: 0x8020,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[1]",
|
||||||
|
description: "Region Domain 1",
|
||||||
|
offset: 0x8022,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[2]",
|
||||||
|
description: "Region Domain 2",
|
||||||
|
offset: 0x8024,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[3]",
|
||||||
|
description: "Region Domain 3",
|
||||||
|
offset: 0x8026,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[4]",
|
||||||
|
description: "Region Domain 4",
|
||||||
|
offset: 0x8028,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[5]",
|
||||||
|
description: "Region Domain 5",
|
||||||
|
offset: 0x802A,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[6]",
|
||||||
|
description: "Region Domain 6",
|
||||||
|
offset: 0x802C,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regdmn[7]",
|
||||||
|
description: "Region Domain 7",
|
||||||
|
offset: 0x802E,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build our SYSTEM_INFO eeprom structure
|
||||||
|
var SYSTEM_INFO = []EEPROM_Value{
|
||||||
|
// Missing values:
|
||||||
|
// cpu
|
||||||
|
// cpuid
|
||||||
|
// flashSize (this is static in unifi's kernel module -_-)
|
||||||
|
// ramsize
|
||||||
|
{
|
||||||
|
name: "vendorid",
|
||||||
|
description: "Vendor Identifier",
|
||||||
|
offset: 0x8010,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "systemid",
|
||||||
|
description: "Device Model/Revision Identifier",
|
||||||
|
offset: 0xC,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
// shortname (we may wanna map boardid for this)
|
||||||
|
{
|
||||||
|
name: "boardrevision",
|
||||||
|
description: "Board Revision for the device",
|
||||||
|
offset: 0x13,
|
||||||
|
length: 0x1,
|
||||||
|
vtype: "hextobase10",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "serialno",
|
||||||
|
description: "Serial Number",
|
||||||
|
offset: 0x0,
|
||||||
|
length: 0x5,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
// manufid
|
||||||
|
// mfgweek
|
||||||
|
// qrid
|
||||||
|
// eth*.macaddr (generated mac's for all eth interfaces)
|
||||||
|
// device.hashid
|
||||||
|
// device.anonid
|
||||||
|
// bt0.macaddr (generated bt mac)
|
||||||
|
{
|
||||||
|
name: "regdmn[]",
|
||||||
|
description: "Region Domain",
|
||||||
|
offset: 0x8020,
|
||||||
|
length: 0x10,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
// cpu_rev_id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build our vars that are similar to running ubnt-tools id
|
||||||
|
var UBNT_TOOLS = []EEPROM_Value{
|
||||||
|
{
|
||||||
|
name: "board.sysid",
|
||||||
|
description: "Device Model/Revision Identifier",
|
||||||
|
offset: 0xC,
|
||||||
|
length: 0x2,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "board.serialno",
|
||||||
|
description: "Serial Number",
|
||||||
|
offset: 0x0,
|
||||||
|
length: 0x5,
|
||||||
|
vtype: "hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "board.bom",
|
||||||
|
description: "Board Bill of Materials Revision Code",
|
||||||
|
offset: 0xD024,
|
||||||
|
length: 0xC,
|
||||||
|
vtype: "str",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(e error) {
|
||||||
|
if e != nil {
|
||||||
|
if strings.Contains(e.Error(), "encoding/hex: invalid byte:") {
|
||||||
|
fmt.Printf("Error: Unable to parse hex, please check your input.\n")
|
||||||
|
} else if strings.Contains(e.Error(), "EOF") {
|
||||||
|
fmt.Printf("Error: Unable to read contents from EEPROM/file.\n")
|
||||||
|
} else if strings.Contains(e.Error(), "encoding/hex: odd length hex string") {
|
||||||
|
fmt.Printf("Error: Incorrect length of input. Please try again.\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Fatal Error!!! ")
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func eeprom_read(vl []EEPROM_Value, f *os.File, key string) string {
|
||||||
|
var offs, leng int64
|
||||||
|
var vtype string
|
||||||
|
|
||||||
|
// Lookup our item
|
||||||
|
for _, v := range vl {
|
||||||
|
if v.name == key {
|
||||||
|
offs = v.offset
|
||||||
|
leng = v.length
|
||||||
|
vtype = v.vtype
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we found it
|
||||||
|
if (offs == 0) && (leng == 0) {
|
||||||
|
fmt.Printf("Error: Invalid key %s!\n", key)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek our file
|
||||||
|
_, err := f.Seek(offs, 0)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
// Make var and read into it
|
||||||
|
b2 := make([]byte, leng)
|
||||||
|
_, err = f.Read(b2)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
// Format as needed depending on type
|
||||||
|
switch vtype {
|
||||||
|
case "hexmac":
|
||||||
|
// Mac is stored in hex, but we need to format the return
|
||||||
|
macstr := net.HardwareAddr(b2[:]).String()
|
||||||
|
return macstr
|
||||||
|
case "hexint":
|
||||||
|
// Int is stored in hex
|
||||||
|
if b2[0]&0x0 == 0x0 {
|
||||||
|
// We start with 0, so strip
|
||||||
|
return strings.TrimPrefix(hex.EncodeToString(b2), `0`)
|
||||||
|
} else {
|
||||||
|
// We do not start with 0, so carry on
|
||||||
|
return hex.EncodeToString(b2)
|
||||||
|
}
|
||||||
|
case "hextobase10":
|
||||||
|
// Hex value needs to be moved to base 10
|
||||||
|
base_conversion, err := strconv.ParseInt(hex.EncodeToString(b2), 16, 64)
|
||||||
|
check(err)
|
||||||
|
return strconv.Itoa(int(base_conversion))
|
||||||
|
case "str":
|
||||||
|
// String value
|
||||||
|
return string(b2)
|
||||||
|
default:
|
||||||
|
// Default is to assume hex
|
||||||
|
return hex.EncodeToString(b2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func return_values(values []EEPROM_Value, file string, filter string) {
|
||||||
|
// Open EEPROM for read only
|
||||||
|
f, err := os.Open(file)
|
||||||
|
defer f.Close()
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
// If select is set, select our item, else return all
|
||||||
|
if len(filter) > 0 {
|
||||||
|
// Read value
|
||||||
|
fmt.Printf("%s\n", eeprom_read(values, f, filter))
|
||||||
|
} else {
|
||||||
|
// read all
|
||||||
|
for _, v := range values {
|
||||||
|
fmt.Printf("%s=%s\n", v.name, eeprom_read(values, f, v.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Start by defining our args
|
||||||
|
argfile := flag.String("file", "/dev/mtd4", "The path to the EEPROM for the device")
|
||||||
|
argboard := flag.Bool("board", false, "Print the board values")
|
||||||
|
argsystem := flag.Bool("systeminfo", false, "Print the system info values")
|
||||||
|
argtools := flag.Bool("tools", false, "Print similar values to ubnt-tools id")
|
||||||
|
argfilter := flag.String("key", "", "Used to select a specific EEPROM value")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Verify we can read our eeprom file
|
||||||
|
if _, err := os.Stat(*argfile); os.IsNotExist(err) {
|
||||||
|
fmt.Printf("Error: Unable to access %s.\n", *argfile)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is board set?
|
||||||
|
if *argboard {
|
||||||
|
return_values(BOARD, *argfile, *argfilter)
|
||||||
|
} else if *argsystem {
|
||||||
|
return_values(SYSTEM_INFO, *argfile, *argfilter)
|
||||||
|
} else if *argtools {
|
||||||
|
return_values(UBNT_TOOLS, *argfile, *argfilter)
|
||||||
|
} else {
|
||||||
|
// Tell user noting was submitted
|
||||||
|
fmt.Fprintf(os.Stderr, "Error Invalid usage of %s:\n", os.Args[0])
|
||||||
|
flag.PrintDefaults()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We be done
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
Loading…
Reference in a new issue