#!/system/bin/sh

PATH=/sbin:/system/sbin:/system/bin:/system/xbin
export PATH

while getopts d op;
do
	case $op in
		d)  dbg_on=1;;
	esac
done
shift $(($OPTIND-1))

scriptname=${0##*/}

uppers=ABCDEFP1234567890
lowers=abcdefp1234567p9

convert_to_pnotation()
{
	result=""
	let i=0
	while ([ $i -lt ${#1} ]) do
		sym=${1:$i:1}
		case $uppers in
			*$sym*) sym=${uppers%$sym*}; result="${result}${lowers:${#sym}:1}";;
			*) result="${result}$sym";;
		esac
		i=$((i + 1))
	done
	echo "$result"
	unset i result
}

debug()
{
	[ $dbg_on ] && echo "Debug: $*"
}

notice()
{
	echo "$*"
	echo "$scriptname: $*" > /dev/kmsg
}

error_and_leave()
{
	local err_msg
	local err_code=$1
	case $err_code in
		1)  err_msg="Error: No response from touch IC";;
		2)  err_msg="Error: Cannot read property $1";;
		3)  err_msg="Error: No matching firmware file found";;
		4)  err_msg="Error: Touch IC is in bootloader mode";;
		5)  err_msg="Error: Touch provides no reflash interface";;
		6)  err_msg="Error: Touch driver is not running";;
	esac
	notice "$err_msg"
	exit $err_code
}

for touch_vendor in $*; do
	debug "searching driver for vendor [$touch_vendor]"
	touch_driver_link=$(ls -l /sys/bus/i2c/drivers/$touch_vendor*/*-*)
	if [ -z "$touch_driver_link" ]; then
		debug "no driver for vendor [$touch_vendor] is running"
		shift 1
	else
		debug "driver for vendor [$touch_vendor] found!!!"
		break
	fi
done

[ -z "$touch_driver_link" ] && error_and_leave 6

touch_path=/sys/devices/${touch_driver_link#*devices/}
debug "sysfs touch path: $touch_path"

[ -f $touch_path/doreflash ] || error_and_leave 5
[ -f $touch_path/poweron ] || error_and_leave 5

debug "wait until driver reports <ready to flash>..."
while true; do
	readiness=$(cat $touch_path/poweron)
	if [ "$readiness" == "1" ]; then
		debug "ready to flash!!!"
		break;
	fi
	sleep 1
	debug "not ready; keep waiting..."
done
unset readiness

device_property=ro.boot.device
hwrev_property=ro.boot.hwrev
firmware_path=/system/vendor/firmware

let dec_cfg_id_boot=0; dec_cfg_id_latest=0;

read_touch_property()
{
	property=""
	debug "retrieving property: [$touch_path/$1]"
	property=$(cat $touch_path/$1 2> /dev/null)
	debug "touch property [$1] is: [$property]"
	[ -z "$property" ] && return 1
	return 0
}

find_latest_config_id()
{
	debug "scanning dir for files matching [$1]"
	str_cfg_id_latest=""
	let dec=0; max=0;
	for file in $(ls $1 2>/dev/null);
	do
		x=${file#*-}; z=${x#*-}; str_hex=${z%%-*};
		let dec=0x$str_hex
		if [ $dec -gt $max ];
		then
			let max=$dec; dec_cfg_id_latest=$dec;
			str_cfg_id_latest=$str_hex
		fi
	done
	unset dec max x z str_hex
	[ -z "$str_cfg_id_latest" ] && return 1
	return 0
}

read_touch_property flashprog || error_and_leave 1
bl_mode=$property
debug "bl mode: $bl_mode"

read_touch_property productinfo || error_and_leave 1
touch_product_id=$property
if [ -z "$touch_product_id" ] || [ "$touch_product_id" == "0" ];
then
	debug "touch ic reports invalid product id"
	error_and_leave 3
fi
debug "touch product id: $touch_product_id"

read_touch_property buildid || error_and_leave 1
str_cfg_id_boot=${property#*-}
let dec_cfg_id_boot=0x$str_cfg_id_boot
debug "touch config id: $str_cfg_id_boot"

product_id=$(getprop $device_property 2> /dev/null)
[ -z "$product_id" ] && error_and_leave 2 $device_property
product_id=${product_id%-*}
debug "product id: $product_id"

hwrev_id=$(getprop $hwrev_property 2> /dev/null)
[ -z "$hwrev_id" ] && error_and_leave 2 $hwrev_property
hwrev_id=${hwrev_id#*x}
hwrev_id=$(convert_to_pnotation $hwrev_id)
debug "hw revision: $hwrev_id"

cd $firmware_path

debug "search for best hw revision match"
hw_mask="-$hwrev_id"
while [ ! -z "$hw_mask" ]; do
	if [ "$hw_mask" == "-" ]; then
		hw_mask=""
	fi
	find_latest_config_id "$touch_vendor-$touch_product_id-*-$product_id$hw_mask.*"
	if [ $? -eq 0 ]; then
		break;
	fi
        hw_mask=${hw_mask%?}
done

[ -z "$str_cfg_id_latest" ] && error_and_leave 3

firmware_file=$(ls $touch_vendor-$touch_product_id-$str_cfg_id_latest-*-$product_id$hw_mask.*)
debug "firmware file for upgrade $firmware_file"

if [ $dec_cfg_id_boot -ne $dec_cfg_id_latest ] || [ "$bl_mode" == "1" ];
then
	debug "forcing firmware upgrade"
	echo 1 > $touch_path/forcereflash
	debug "sending reflash command"
	echo $firmware_file > $touch_path/doreflash
	read_touch_property flashprog || error_and_leave 1
	bl_mode=$property

	[ "$bl_mode" == "1" ] && error_and_leave 4

	read_touch_property buildid || error_and_leave 1
	str_cfg_id_new=${property#*-}
	debug "firmware config ids: expected $str_cfg_id_latest, current $str_cfg_id_new"

	notice "Touch firmware config id at boot time $str_cfg_id_boot"
	notice "Touch firmware config id in the file $str_cfg_id_latest"
	notice "Touch firmware config id currently programmed $str_cfg_id_new"
else
	notice "Touch firmware is up to date"
fi

unset device_property hwrev_property
unset str_cfg_id_boot str_cfg_id_latest str_cfg_id_new
unset dec_cfg_id_boot dec_cfg_id_latest
unset hwrev_id product_id touch_product_id
unset touch_driver_link firmware_path touch_path
unset bl_mode dbg_on hw_mask firmware_file property

return 0