#! /bin/sh

# Some constants
JTAG_CMD_FILE="/tmp/jtag_cmd"
JTAG_OUTPUT_FILE="/tmp/jtag_output"

# Debugging variable
DEBUG=0

# Prints the wanted line from the specified file
function read_line {
	if [ $# -ne 2 ]
	then
		echo "Usage: read_line {FILE} {LINE_NUMBER}"
		return -1
	fi

	FILE="$1"
	LINE_NUMBER="$2"

	LINE=$(sed -n "${LINE_NUMBER}{p;q}" ${FILE})
	[ "${LINE}" == "" ] && return -1

	echo ${LINE}
	return 0
}

function jtag_cable {
	CABLE=""
	INTERFACE=""
	if [ $# -eq 1 ]
	then
		CABLE=$1
		INTERFACE=""
	elif [ $# -eq 2 ]
	then
		CABLE=$1
		INTERFACE="interface=$2"
	else
		return -1
	fi

	echo "cable \"${CABLE}\" ${INTERFACE}" > "${JTAG_CMD_FILE}"

	return 0
}

# Function to scan what is present on the selected JTAG lanes
# Creates some temporary files that needs to be removed with 'jtag_clean'
function jtag_detect {
	if [ $# -eq 1 ]
	then
		jtag_cable "$1"
	elif  [ $# -eq 2 ]
	then
		jtag_cable "$1" "$2"
	else
		return -1
	fi

	result=$?
	if [ ${result} -ne 0 ]
	then
		echo "Usage: jtag_detect {CABLE_NAME} [INTERFACE_NUMBER]"
		echo "    with CABLE_NAME: 'osb', 'tacb', 'Viavi FMA'"
		return ${result}
	fi

	echo "detect" >> "${JTAG_CMD_FILE}"

	if [ $DEBUG -ne 0 ]
	then
		echo
		echo "JTAG INPUT:"
		cat "${JTAG_CMD_FILE}"
		echo
	fi

	# Let's set a timeout of 3 seconds for this command - just in case it freezes
	/usr/bin/timeout 3 /usr/bin/jtag "${JTAG_CMD_FILE}" > "${JTAG_OUTPUT_FILE}"

	# File is empty - Either an error occured or nothing was detected
	[ ! -s "${JTAG_OUTPUT_FILE}" ] && return -1

	if [ $DEBUG -ne 0 ]
	then
		echo
		echo "JTAG OUTPUT:"
		cat "${JTAG_OUTPUT_FILE}"
		echo
	fi

	return 0
}

function jtag_flash_usage {
	echo "Usage: jtag_flash {CABLE_NAME} [INTERFACE_NUMBER] {JTAG_INDEX} {FLASH_COMMAND}"
	echo "    with CABLE_NAME: 'osb', 'tacb', 'Viavi FMA'"

	return 0
}

# Function to flash what is on the selected JTAG lanes
# Creates some temporary files that needs to be removed with 'jtag_clean'
function jtag_flash {
	CABLE_NAME=""
	INTERFACE_NUMBER=""
	JTAG_INDEX=""
	FLASH_COMMAND=""

	if [ $# -eq 3 ]
	then
		CABLE_NAME=$1
		JTAG_INDEX=$2
		FLASH_COMMAND=$3
	elif [ $# -eq 4 ]
	then
		CABLE_NAME=$1
		INTERFACE_NUMBER=$2
		JTAG_INDEX=$3
		FLASH_COMMAND=$4
	else
		jtag_flash_usage
		return -1
	fi

	if [ -z ${INTERFACE_NUMBER} ]
	then
		jtag_cable "${CABLE_NAME}"
	else
		jtag_cable "${CABLE_NAME}" "${INTERFACE_NUMBER}"
	fi

	result=$?
	if [ ${result} -ne 0 ]
	then
		jtag_flash_usage
		return ${result}
	fi

	echo "detect" >> "${JTAG_CMD_FILE}"
	echo "part ${JTAG_INDEX}" >> "${JTAG_CMD_FILE}"
	echo "${FLASH_COMMAND}" >> "${JTAG_CMD_FILE}"

	if [ $DEBUG -ne 0 ]
	then
		echo
		echo "JTAG INPUT:"
		cat "${JTAG_CMD_FILE}"
		echo
	fi

	/usr/bin/jtag "${JTAG_CMD_FILE}" > "${JTAG_OUTPUT_FILE}"

	if [ $DEBUG -ne 0 ]
	then
		echo
		echo "JTAG OUTPUT:"
		cat "${JTAG_OUTPUT_FILE}"
		echo
	fi

	return 0
}

# Function to clean the temporary files
function jtag_clean {
	[ -f "${JTAG_CMD_FILE}" ] && rm "${JTAG_CMD_FILE}"
	[ -f "${JTAG_OUTPUT_FILE}" ] && rm "${JTAG_OUTPUT_FILE}"
}

# Retrieves the chain length from the output file
function jtag_get_chain_length {
	LINE=$(read_line ${JTAG_OUTPUT_FILE} 2)
	[ $? -ne 0 ] && return -1

	CHAIN_LENGTH=${LINE: -1}

	echo ${CHAIN_LENGTH}
	return 0
}

# Retrieves the device ID from the output file
function jtag_get_device_id {
	if [ $# -eq 0 ]
	then
		OFFSET=0
	elif [ $# -eq 1 ]
	then
		OFFSET=$1
	else
		echo "Usage: $0 [DEVICE_NUMBER]"
		return -1
	fi

	LINE_INDEX=$((3 + 5 * ${OFFSET}))
	LINE=$(read_line ${JTAG_OUTPUT_FILE} ${LINE_INDEX})
	[ $? -ne 0 ] && return -1

	DEVICE_ID=$(echo ${LINE} | cut -f2 -d "(" | cut -f1 -d ")")

	echo ${DEVICE_ID}
	return 0
}

# This function should not be called
# It is only provided as an example
function jtag_test {
	if [ $# -eq 1 ]
	then
		jtag_detect "$1"
	elif  [ $# -eq 2 ]
	then
		jtag_detect "$1" "$2"
	else
		echo "Usage: $0 {CABLE_NAME} [INTERFACE_NUMBER]"
		return -1
	fi

	[ $? -ne 0 ] && echo "Error detecting the JTAG chain of '$1'" && exit -1 || echo "Detected the JTAG chain of '$1'"

	Chain_Length=$(jtag_get_chain_length)
	[ $? -ne 0 ] && echo "Error reading the Chain Length" && exit -1 || echo "Chain_Length: ${Chain_Length}"

	iter=0
	while [ ${iter} -lt ${Chain_Length} ]
	do
		let iter++
		Device_Id=$(jtag_get_device_id ${iter})
		[ $? -ne 0 ] && echo "Error reading the Device ID" && exit -1 || echo "Device_Id: ${Device_Id}"
	done
}
