#!/bin/bash -e
#
# Copyright (c) 2016-2018 Robert Nelson <robertcnelson@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

# Include defaults if available
if [ -f /etc/default/bb-wl18xx ] ; then
	. /etc/default/bb-wl18xx
fi

cylon_leds () {
	if [ -e /sys/class/leds/beaglebone\:green\:usr0/trigger ] ; then
		BASE=/sys/class/leds/beaglebone\:green\:usr
		echo none > ${BASE}0/trigger
		echo none > ${BASE}1/trigger

		STATE=1
		while : ; do
			case $STATE in
			1)	echo 255 > ${BASE}0/brightness
				echo 0   > ${BASE}1/brightness
				STATE=2
				;;
			2)	echo 255 > ${BASE}1/brightness
				echo 0   > ${BASE}0/brightness
				STATE=1
				;;
			*)	echo 255 > ${BASE}0/brightness
				echo 0   > ${BASE}1/brightness
				STATE=2
				;;
			esac
			#bashsism...
			#possible bashism in bb-wl18xx-wlan0 line 45 (sleep only takes one integer):
			sleep 0.1
		done
	fi
}

set_wlan_0_mac () {
	if [ -f ${firmware} ] ; then
		firmware_dump=$(hexdump -ve '1/1 "%.2x"' ${firmware} -n 12 | awk '{print toupper($0)}')
		offset0=$(echo ${firmware_dump} | cut -b 23-24)
		offset1=$(echo ${firmware_dump} | cut -b 21-22)
		offset2=$(echo ${firmware_dump} | cut -b 13-14)
		offset3=$(echo ${firmware_dump} | cut -b 11-12)
		offset4=$(echo ${firmware_dump} | cut -b 9-10)
		offset5=$(echo ${firmware_dump} | cut -b 7-8)
		current_mac="${offset0}:${offset1}:${offset2}:${offset3}:${offset4}:${offset5}"
		echo "${firmware}=[${current_mac}]"

		if [ ! "x${current_mac}" = "x${wlan_0_mac}" ] ; then

			cylon_leds & CYLON_PID=$!

			offset0=$(echo ${wlan_0_mac} | cut -b 1-2)
			offset1=$(echo ${wlan_0_mac} | cut -b 4-5)
			offset2=$(echo ${wlan_0_mac} | cut -b 7-8)
			offset3=$(echo ${wlan_0_mac} | cut -b 10-11)
			offset4=$(echo ${wlan_0_mac} | cut -b 13-14)
			offset5=$(echo ${wlan_0_mac} | cut -b 16-17)

			printf '\x'${offset0}'' | dd conv=notrunc of=${firmware} bs=1 seek=$((0x0000000b)) status=none
			printf '\x'${offset1}'' | dd conv=notrunc of=${firmware} bs=1 seek=$((0x0000000a)) status=none
			printf '\x'${offset2}'' | dd conv=notrunc of=${firmware} bs=1 seek=$((0x00000006)) status=none
			printf '\x'${offset3}'' | dd conv=notrunc of=${firmware} bs=1 seek=$((0x00000005)) status=none
			printf '\x'${offset4}'' | dd conv=notrunc of=${firmware} bs=1 seek=$((0x00000004)) status=none
			printf '\x'${offset5}'' | dd conv=notrunc of=${firmware} bs=1 seek=$((0x00000003)) status=none

			echo "Writing mac address: [${wlan_0_mac}] to file: ${firmware}"

			if [ -f /boot/initrd.img-`uname -r` ] ; then
				echo "updating: /boot/initrd.img-`uname -r`"
				update-initramfs -u -k `uname -r` || true
			else
				echo "creating: /boot/initrd.img-`uname -r`"
				update-initramfs -c -k `uname -r` || true
			fi
			sync
			echo "/boot/initrd.img-`uname -r`: write complete"
			[ -e /proc/$CYLON_PID ]  && kill $CYLON_PID
			if [ -e /sys/class/leds/beaglebone\:green\:usr0/trigger ] ; then
				echo heartbeat > /sys/class/leds/beaglebone\:green\:usr0/trigger
				echo mmc0 > /sys/class/leds/beaglebone\:green\:usr1/trigger
			fi
		fi
	fi
}

use_backup_wlan_0_mac () {
	if [ -f /etc/cpsw_0_mac ] ; then
		wlan_0_mac=$(cat /etc/wlan_0_mac | awk '{print toupper($0)}')
	else
		wlan_0_mac="00:00:00:00:00:00"
	fi
}

set_wlan_0_mac_from_wl18xx () {
	wlan_0_mac="00:00:00:00:00:00"
	echo ${wlan_0_mac} > /etc/wlan_0_mac
	echo "wlan_0_mac=[${wlan_0_mac}], this forces internal wl18xx mac address..."
	set_wlan_0_mac
}

set_wlan_0_mac_from_eeprom () {
	if [ -f ${eeprom} ] ; then
		wlan_0_mac=$(hexdump -e '8/1 "%c"' ${eeprom} -n 72 | tail -1 | cut -b 5-8 || true)
		if [ ! "x${wlan_0_mac}" = "xA335" ] ; then
			wlan_0_mac=$(hexdump -e '8/1 "%c"' ${eeprom} -n 72 | tail -1 | cut -b 5-16 | sed 's/\(..\)/\1:/g;s/:$//' | awk '{print toupper($0)}' || true)
			echo ${wlan_0_mac} > /etc/wlan_0_mac
		else
			use_backup_wlan_0_mac
		fi
	else
		use_backup_wlan_0_mac
	fi

	echo "wlan_0_mac=[${wlan_0_mac}]"
	set_wlan_0_mac
}

set_wlan_0_mac_from_cpsw_0 () {
	if [ -f /etc/cpsw_0_mac ] ; then
		cpsw_0_mac=$(cat /etc/cpsw_0_mac | awk '{print toupper($0)}')
	else
		mac_address="/proc/device-tree/ocp/ethernet@4a100000/slave@4a100200/mac-address"
		if [ -f ${mac_address} ] ; then
			cpsw_0_mac=$(hexdump -v -e '1/1 "%02X" ":"' ${mac_address} | sed 's/.$//' | awk '{print toupper($0)}')
		else
			cpsw_0_mac="00:00:00:00:00:00"
		fi
	fi
	wlan_0_mac="${cpsw_0_mac}"
	echo "wlan_0_mac=[${wlan_0_mac}]"
	set_wlan_0_mac
}

set_wlan_0_mac_from_cpsw_4 () {
	if [ -f /etc/cpsw_0_mac ] ; then
		cpsw_0_mac=$(cat /etc/cpsw_0_mac | awk '{print toupper($0)}')
	else
		mac_address="/proc/device-tree/ocp/ethernet@4a100000/slave@4a100200/mac-address"
		if [ -f ${mac_address} ] ; then
			cpsw_0_mac=$(hexdump -v -e '1/1 "%02X" ":"' ${mac_address} | sed 's/.$//' | awk '{print toupper($0)}')
		else
			cpsw_0_mac="00:00:00:00:00:00"
		fi
	fi

	if [ -f /usr/bin/bc ] ; then
		mac_0_prefix=$(echo ${cpsw_0_mac} | cut -c 1-14)

		cpsw_0_6=$(echo ${cpsw_0_mac} | awk -F ':' '{print $6}')
		#bc cuts off leading zero's, we need ten/ones value
		cpsw_res=$(echo "obase=16;ibase=16;$cpsw_0_6 + 104" | bc)

		cpsw_4_mac=${mac_0_prefix}:$(echo ${cpsw_res} | cut -c 2-3)
	else
		cpsw_4_mac="00:00:00:00:00:00"
	fi
	wlan_0_mac="${cpsw_4_mac}"
	echo "wlan_0_mac=[${wlan_0_mac}]"
	set_wlan_0_mac
}

set_wlan_0_mac_from_bb_wl18xx () {
	wlan_0_mac=$(echo ${USE_WL18XX_MAC_ADDRESS} | awk '{print toupper($0)}')
	echo "wlan_0_mac=[${wlan_0_mac}]"
	set_wlan_0_mac
}

start_tether () {
	if [ -f /usr/sbin/rfkill ] ; then
		/usr/sbin/rfkill unblock all || true
	fi
	if [ "x${TETHER_ENABLED}" = "xyes" ] ; then
		/usr/bin/bb-wl18xx-tether || true
	fi
}

board=$(cat /proc/device-tree/model | sed "s/ /_/g" | tr -d '\000')
case "${board}" in
TI_AM335x_BeagleBone_Green_Wireless)
	eeprom="/sys/bus/i2c/devices/0-0050/eeprom"
	firmware="/lib/firmware/ti-connectivity/wl1271-nvs.bin"
	if [ "x${USE_INTERNAL_WL18XX_MAC_ADDRESS}" = "xyes" ] ; then
		set_wlan_0_mac_from_wl18xx
	else
		if [ "x${USE_WL18XX_MAC_ADDRESS}" = "x" ] ; then
			set_wlan_0_mac_from_eeprom
		else
			set_wlan_0_mac_from_bb_wl18xx
		fi
		#make sure wl18xx_wl_en is on...
		if [ -f /sys/class/leds/wl18xx_wl_en/brightness ] ; then
			echo 1 > /sys/class/leds/wl18xx_wl_en/brightness || true
		fi
	fi
	start_tether
	;;
TI_AM335x_BeagleBone_Black_Wireless)
	firmware="/lib/firmware/ti-connectivity/wl1271-nvs.bin"
	if [ "x${USE_INTERNAL_WL18XX_MAC_ADDRESS}" = "xyes" ] ; then
		set_wlan_0_mac_from_wl18xx
	else
		if [ "x${USE_WL18XX_MAC_ADDRESS}" = "x" ] ; then
			set_wlan_0_mac_from_cpsw_0
		else
			set_wlan_0_mac_from_bb_wl18xx
		fi
	fi
	start_tether
	;;
TI_AM335x_BeagleBone_Black_Wireless_RoboticsCape)
	firmware="/lib/firmware/ti-connectivity/wl1271-nvs.bin"
	if [ "x${USE_INTERNAL_WL18XX_MAC_ADDRESS}" = "xyes" ] ; then
		set_wlan_0_mac_from_wl18xx
	else
		if [ "x${USE_WL18XX_MAC_ADDRESS}" = "x" ] ; then
			set_wlan_0_mac_from_cpsw_0
		else
			set_wlan_0_mac_from_bb_wl18xx
		fi
	fi
	start_tether
	;;
TI_AM335x_BeagleBone_Blue)
	firmware="/lib/firmware/ti-connectivity/wl1271-nvs.bin"
	if [ "x${USE_INTERNAL_WL18XX_MAC_ADDRESS}" = "xyes" ] ; then
		set_wlan_0_mac_from_wl18xx
	else
		if [ "x${USE_WL18XX_MAC_ADDRESS}" = "x" ] ; then
			set_wlan_0_mac_from_cpsw_0
		else
			set_wlan_0_mac_from_bb_wl18xx
		fi
	fi
	start_tether
	;;
TI_AM335x_BeagleBone_Black_Gateway_Cape)
	firmware="/lib/firmware/ti-connectivity/wl1271-nvs.bin"
	if [ "x${USE_INTERNAL_WL18XX_MAC_ADDRESS}" = "xyes" ] ; then
		set_wlan_0_mac_from_wl18xx
	else
		if [ "x${USE_WL18XX_MAC_ADDRESS}" = "x" ] ; then
			set_wlan_0_mac_from_cpsw_4
		else
			set_wlan_0_mac_from_bb_wl18xx
		fi
	fi
	start_tether
	;;
*)
	;;
esac
