#!/bin/sh

set -e

log() {
	echo "$1"
}

# AutoRun Recovery
if [ $# -lt 3 ]
then
	log "Verify input argument fail!"
	log "Usage: recovery.sh [I2C_BUS] [I2C_ID] [CAM_NAME]"
	log "    [I2C_BUS]: I2C bus index, 9 is a example"
	log "    [I2C_ID]: I2C device address, 0x48 is a example (hex)"
	log "    [CAM_NAME]: Camera product name, as follows:"
	log "                - TEVS-AR0144"
	log "                - TEVS-AR0145-M"
	log "                - TEVS-AR0234"
	log "                - TEVS-AR0521"
	log "                - TEVS-AR0522"
	log "                - TEVS-AR0522-M"
	log "                - TEVS-AR0821"
	log "                - TEVS-AR0822"
	log "                - TEVS-AR0822-M"
	log "                - TEVS-AR1335"
	exit 1
fi

NOW_PATH=$(pwd)

I2C_BUS=$1
RAW_ID=$2
CAM_NAME=$3
CAM_VER="25.10.00.01"

case "$RAW_ID" in
    0x*|0X*)
        I2C_ID_HEX="${RAW_ID#0x}"
        I2C_ID="${I2C_ID_HEX#0X}"
        ;;
    *)
        I2C_ID="${RAW_ID#0X}"
        ;;
esac

case "$CAM_NAME" in
	"TEVS-AR0144")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0144_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0145-M")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0145m_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0234")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0234_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0521")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0521_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0522")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0522_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0522-M")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0522m_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0821")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0821_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0822")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0822_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR0822-M")
		BIN_FILE="$NOW_PATH/bin/tevs_ar0822m_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	"TEVS-AR1335")
		BIN_FILE="$NOW_PATH/bin/tevs_ar1335_MSPM0G3507_nortos_ticlang_w_map_$CAM_VER.bin"
		;;
	*)
		log "Unknow camera product name"
		exit 1
		;;
esac

# resource check
if [ ! -f "$BIN_FILE" ]; then
    log "Bin file not found: $BIN_FILE"
    exit 1
fi

get_value() {
    list="$1"
    idx="$2"

    set -- $list
    i=0
    for v in "$@"; do
        if [ "$i" -eq "$idx" ]; then
            echo "$v"
            return
        fi
        i=$((i+1))
    done
}

log "TechNexion VLS-GM2 camera recovery tool for NVIDIA Orin Nano"
log "TEVS firmware version $CAM_VER"

# Camera device list (index:bus-addr)
CAM_DEVICES="
9-0039
9-003a
9-003b
9-003c
10-0049
10-004a
10-004b
10-004c
"

CAM_FOUND_LIST=""
CAM_EXP_LIST=""
CAM_EXP_BUS_LIST=""
CAM_EXP_DEV_LIST=""
CAM_SER_BUS_LIST=""
CAM_SER_DEV_LIST=""

idx=0
for dev in $CAM_DEVICES; do
    path="/sys/bus/i2c/devices"

    cam_found=0
    cam_expander=0
    i2cbus=0
    i2cdev=0
	ser_i2cbus=0
	ser_i2cdev=0
	
    # check camera driver
    if [ -L "$path/$dev/driver" ]; then
        log "Camera$idx found"
        cam_found=1
    else
        log "Camera$idx cannot found"
    fi

    # check serializer adaptor
	for s in "$path"/"$dev"/supplier:i2c:*; do
        if [ -e "$s" ]; then
            SUPPLIER="${s##*:}"
            i2cbus="${SUPPLIER%-*}"
            i2cdev_raw="${SUPPLIER#*-}"
            i2cdev="0x$(printf '%x' 0x$i2cdev_raw)"
            cam_expander=1
            log "Camera$idx found serializer adaptor"
			
            break
        fi
    done

    if [ "$cam_expander" -eq 0 ]; then
        log "Camera$idx cannot found serializer adaptor"
    fi

    CAM_FOUND_LIST="$CAM_FOUND_LIST $cam_found"
    CAM_EXP_LIST="$CAM_EXP_LIST $cam_expander"
    CAM_EXP_BUS_LIST="$CAM_EXP_BUS_LIST $i2cbus"
    CAM_EXP_DEV_LIST="$CAM_EXP_DEV_LIST $i2cdev"
	
	idx=$((idx+1))
done

match=0
idx=0
for dev in $CAM_DEVICES; do
	i2cbus="${dev%-*}"
	i2cdev_raw="${dev#*-}"
	i2cdev_hex=$(printf '%x' 0x$i2cdev_raw)
	i2cdev=$(printf '%d' 0x$i2cdev_raw)
	
	cam_found=$(get_value "$CAM_FOUND_LIST" "$idx")
	cam_expander=$(get_value "$CAM_EXP_LIST" "$idx")
	cam_exp_bus=$(get_value "$CAM_EXP_BUS_LIST" "$idx")
	cam_exp_dev=$(get_value "$CAM_EXP_DEV_LIST" "$idx")
	
	if [ "$I2C_BUS" -eq "$i2cbus" ] && [ "`printf '%d' 0x$I2C_ID`" -eq "$i2cdev" ]; then
		match=1
		
		if [ "$cam_found" -eq 1 ]; then
			log "Camera$idx is working, please update the camera firmware using the usual methods."
		elif [ "$cam_expander" -eq 1 ]; then
			vizion-ctl -fu sensor="$BIN_FILE" \
				--i2c-bus "$I2C_BUS" \
				--slave-id "`printf '%d' 0x$I2C_ID`" \
				--bsl-hook "
					echo \"Watting for the MCU's last response time\"
					sleep 10
					sudo i2ctransfer -f -y $cam_exp_bus w2@$cam_exp_dev 0x01 0xef
					sudo i2ctransfer -f -y $cam_exp_bus w2@$cam_exp_dev 0x01 0xff
					sleep 0.1
					sudo i2ctransfer -f -y $cam_exp_bus w2@$cam_exp_dev 0x01 0xfb" \
				--recovery
		else
			log "Please connect Camera$idx with serializer adaptor"
		fi
	fi
	
	idx=$((idx+1))
done

if [ "$match" -eq 0 ]; then
	log "Change camera device I2C bus"
	
	# Camera device list (index:bus-addr)
	CAM_DEVICES="
	9-0049
	9-004a
	9-004b
	9-004c
	10-0039
	10-003a
	10-003b
	10-003c
	"

	CAM_FOUND_LIST=""
	CAM_EXP_LIST=""
	CAM_EXP_BUS_LIST=""
	CAM_EXP_DEV_LIST=""
	CAM_SER_BUS_LIST=""
	CAM_SER_DEV_LIST=""

	idx=0
	for dev in $CAM_DEVICES; do
		path="/sys/bus/i2c/devices"

		cam_found=0
		cam_expander=0
		i2cbus=0
		i2cdev=0
		ser_i2cbus=0
		ser_i2cdev=0
		
		# check camera driver
		if [ -L "$path/$dev/driver" ]; then
			log "Camera$idx found"
			cam_found=1
		else
			log "Camera$idx cannot found"
		fi

		# check serializer adaptor
		for s in "$path"/"$dev"/supplier:i2c:*; do
			if [ -e "$s" ]; then
				SUPPLIER="${s##*:}"
				i2cbus="${SUPPLIER%-*}"
				i2cdev_raw="${SUPPLIER#*-}"
				i2cdev="0x$(printf '%x' 0x$i2cdev_raw)"
				cam_expander=1
				log "Camera$idx found serializer adaptor"
				
				break
			fi
		done

		if [ "$cam_expander" -eq 0 ]; then
			log "Camera$idx cannot found serializer adaptor"
		fi

		CAM_FOUND_LIST="$CAM_FOUND_LIST $cam_found"
		CAM_EXP_LIST="$CAM_EXP_LIST $cam_expander"
		CAM_EXP_BUS_LIST="$CAM_EXP_BUS_LIST $i2cbus"
		CAM_EXP_DEV_LIST="$CAM_EXP_DEV_LIST $i2cdev"
		
		idx=$((idx+1))
	done

	match=0
	idx=0
	for dev in $CAM_DEVICES; do
		i2cbus="${dev%-*}"
		i2cdev_raw="${dev#*-}"
		i2cdev_hex=$(printf '%x' 0x$i2cdev_raw)
		i2cdev=$(printf '%d' 0x$i2cdev_raw)
		
		cam_found=$(get_value "$CAM_FOUND_LIST" "$idx")
		cam_expander=$(get_value "$CAM_EXP_LIST" "$idx")
		cam_exp_bus=$(get_value "$CAM_EXP_BUS_LIST" "$idx")
		cam_exp_dev=$(get_value "$CAM_EXP_DEV_LIST" "$idx")
		
		if [ "$I2C_BUS" -eq "$i2cbus" ] && [ "`printf '%d' 0x$I2C_ID`" -eq "$i2cdev" ]; then
			match=1
			
			if [ "$cam_found" -eq 1 ]; then
				log "Camera$idx is working, please update the camera firmware using the usual methods."
			elif [ "$cam_expander" -eq 1 ]; then
				vizion-ctl -fu sensor="$BIN_FILE" \
					--i2c-bus "$I2C_BUS" \
					--slave-id "`printf '%d' 0x$I2C_ID`" \
					--bsl-hook "
						echo \"Watting for the MCU's last response time\"
						sleep 10
						sudo i2ctransfer -f -y $cam_exp_bus w2@$cam_exp_dev 0x01 0xef
						sudo i2ctransfer -f -y $cam_exp_bus w2@$cam_exp_dev 0x01 0xff
						sleep 0.1
						sudo i2ctransfer -f -y $cam_exp_bus w2@$cam_exp_dev 0x01 0xfb" \
					--recovery
			else
				log "Please connect Camera$idx with serializer adaptor"
			fi
		fi
		
		idx=$((idx+1))
	done
fi

if [ "$match" -eq 0 ]; then
	log "No camera match with user specific device"
fi
