#!/bin/sh
#===============================================================================
#
#  Copyright (C) 2012-2026, Digi International Inc.
#  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 version 2 as published by
#  the Free Software Foundation.
#
#
#  !Description: Initialize bluetooth hardware
#
#===============================================================================

# Bluetooth power GPIO
BT_PWR_GPIO_NR="##BT_GPIO##"

# set_gpio_value <gpio_nr> <value>
set_gpio_value() {
	gpioset ${1}=${2}
}

# powercycle_gpio <gpio_nr>
powercycle_gpio() {
	gpioset ${1}=0
	sleep .2
	gpioset ${1}=1
	sleep .2
}

error() {
	echo ${1}
	exit 1
}

bluetooth_init() {
	# Get MAC address from the device tree. Use a default value if it has not been set.
	BT_MACADDR="$(hexdump -ve '1/1 "%02X" ":"' /proc/device-tree/bluetooth/mac-address 2>/dev/null | sed 's/:$//g')"
	if [ -z "${BT_MACADDR}" ] || [ "${BT_MACADDR}" = "00:00:00:00:00:00" ]; then
		BT_MACADDR="00:04:F3:FF:FF:BB"
	fi

	# Use a sub-shell here to change to firmware directory
	(
		cd /lib/firmware/ar3k/1020200

		# Update the MAC address file only if it has changed.
		FW_MAC="ar3kbdaddr.pst"
		[ -f "${FW_MAC}" ] && [ "$(cat ${FW_MAC})" = "${BT_MACADDR}" ] || echo ${BT_MACADDR} > ${FW_MAC}

		# Symlink the correct firmware file depending on region code
		JPN_REGCODE="0x2"
		REGCODE="$(cat /proc/device-tree/digi,hwid,cert 2>/dev/null | tr -d '\0')"
		BT_CLASS_LINK="PS_ASIC.pst"
		BT_CLASS_FILE="PS_ASIC_class_1.pst"
		if [ -n "${REGCODE}" ] && [ "${JPN_REGCODE}" = "${REGCODE}" ]; then
			BT_CLASS_FILE="PS_ASIC_class_2.pst"
		fi
		if ! cmp -s ${BT_CLASS_FILE} ${BT_CLASS_LINK}; then
			ln -sf ${BT_CLASS_FILE} ${BT_CLASS_LINK}
		fi
		# Remove not used configuration and readme files
		# -- Do not quote the subcommand to avoid leading/trailing whitespace
		# -- being part of the file name.
		rm -f $(echo PS_ASIC_class_?.pst | sed -e "s,${BT_CLASS_FILE},,g") readme.txt
	)

	# Start the Bluetooth driver and bring up the interface
	HCIATTACH_LOG="/var/log/hciattach.log"
	BT_CMD="HCIATTACH"
	RETRIES="5"
	while [ "${RETRIES}" -gt "0" ]; do
		case "${BT_CMD}" in
		HCIATTACH)
			# Reset BT
			killproc hciattach
			powercycle_gpio "${BT_PWR_GPIO_NR}"
			if hciattach ttyBt ath3k 4000000 >${HCIATTACH_LOG} 2>&1; then
				BT_CMD="HCICONFIG_UP"
			else
				BT_ERROR="FAILED (hciattach)"
				BT_CMD="BT_INIT_FAIL"
			fi
			;;
		HCICONFIG_UP)
			if hciconfig hci0 up; then
				break
			else
				BT_ERROR="FAILED (hciconfig up)"
				BT_CMD="BT_INIT_FAIL"
			fi
			;;
		BT_INIT_FAIL)
			RETRIES="$((RETRIES - 1))"
			BT_CMD="HCIATTACH"
			;;
		esac
	done
	[ "${RETRIES}" = "0" ] && error "${BT_ERROR}"
}

# Source function library
. /etc/init.d/functions

case "$1" in
	start)
		if [ -d "/proc/device-tree/bluetooth" ]; then
			if [ "$(tr -d '\0' 2>/dev/null </proc/device-tree/bluetooth/status)" != "disabled" ]; then
				echo -n "Starting bluetooth hardware: "
				bluetooth_init
				echo "${BT_ERROR:-done.}"
			fi
		fi
		;;
	stop)
		if [ -d "/sys/class/bluetooth/hci0" ]; then
			echo -n "Stopping bluetooth hardware: "
			hciconfig hci0 down || BT_ERROR="FAILED (hciconfig down)"
			killproc hciattach
			# Power down bluetooth
			set_gpio_value "${BT_PWR_GPIO_NR}" 0
			echo "${BT_ERROR:-done.}"
		fi
		;;
	restart)
		$0 stop
		sleep 1
		$0 start
		;;
	*)
		echo "Usage: $0 {start|stop|restart}"
		exit 1
		;;
esac
