#!/bin/sh

module_no="S10E02C05"
module_type="deserial"
makefille_file="Makefile"
version_file="version.mk"
version_def="1.0.0"

if [ -z "$1" ]; then
	cat <<EOF
$(basename $0) <$module_type> [version] [force] - create a new $module_type with version
  $module_type - new $module_type name for lib<$module_type>.so
  version - the version for this $module_type, default ${version_def}
  force   - create or update force, be careful!
eg: new xyz 0.0.1 -- create libxyz.so.0.0.1 $module_type
    new xyz 1.1.0 -- update libxyz.so.1.1.0 version
EOF
	exit 0
else
	module=$1
fi

if [ -z "$2" ]; then
	version=${version_def}
else
	version=$2
	ver_set=y
fi

if [ ! -z "$3" ]; then
	force=y
fi

# gen dir for module
# $1 - module name
gen_dir()
{
	if [ ! -z "$1" ] && [ ! -d "$1" ]; then
		mkdir -p $1
	fi
}

# gen Makefile for module
# $1 - module name
gen_makefile()
{
	makefile_f=$1/${makefille_file}
	if [ -f "$makefile_f" ] && [ -z "$force" ]; then
		echo "$makefile_f exist error"
		exit 1
	fi

	echo "GEN $makefile_f"
	cat <<EOF >$makefile_f
-include ./version.mk

ifeq (\${BUILD_OUTPUT_PATH},)
export BUILD_OUTPUT_PATH=\$(shell pwd)
endif

TARGET = \$(notdir \$(shell pwd))

ifneq (\${version},)
upv = \$(TARGET)
endif

include ../Makefile
EOF
}

# gen version.mk for module
# $1 - module name
gen_version()
{
	version_f=$1/${version_file}
	if [ -f "$version_f" ]; then
		if [ -z "$ver_set" ] && [ -z "$force" ]; then
			echo "$version_f exist error"
			exit 1
		else
			v_major_o=$(cat $version_f |grep 'MAJOR' |awk -F '= ' '{print $2}')
			v_minor_o=$(cat $version_f |grep 'MINOR' |awk -F '= ' '{print $2}')
			v_patch_o=$(cat $version_f |grep 'PATCH' |awk -F '= ' '{print $2}')
			v_update=y
		fi
	else
		echo "GEN $version_f"
	fi
	# get ver
	v_major=`echo $version |awk -F '.' '{print $1}'`
	v_minor=`echo $version |awk -F '.' '{print $2}'`
	v_patch=`echo $version |awk -F '.' '{print $3}'`
	# get number
	v_major=${v_major//[^0-9]/}
	v_minor=${v_minor//[^0-9]/}
	v_patch=${v_patch//[^0-9]/}
	if [ -z "$v_major" ]; then
		v_major=0
	fi
	if [ -z "$v_minor" ]; then
		v_minor=0
	fi
	if [ -z "$v_patch" ]; then
		v_patch=0
	fi

	if [ ! -z "$v_update" ]; then
		echo "UPD $version_f: $v_major_o.$v_minor_o.$v_patch -> $v_major.$v_minor.$v_patch"
		if [ -z "$force" ]; then
			if [ $v_major -lt $v_major_o ]; then
				echo "version major $v_major < $v_major_o error"
				exit 1
			elif [ $v_major -eq $v_major_o ]; then
				if [ $v_minor -lt $v_minor_o ]; then
					echo "version minor $v_minor < $v_minor_o error"
					exit 1
				elif [ $v_minor -eq $v_minor_o ]; then
					if [ $v_patch -lt $v_patch_o ]; then
						echo "version patch $v_patch < $v_patch_o error"
						exit 1
					elif [ $v_patch -eq $v_patch_o ]; then
						echo "version $v_major.$v_minor.$v_patch not need update"
						return 0
					fi
				fi
			fi
		fi
	fi

	cat <<EOF > $version_f
SO_VERSION_MAJOR = ${v_major}
SO_VERSION_MINOR = ${v_minor}
SO_VERSION_PATCH = ${v_patch}
EOF
}

# gen source for module
# $1 - module name
gen_source()
{
	source_files=$(find $1 -maxdepth 1 -type f -name "*.c")
	if [ ! -z "$source_files" ]; then
		return 0
	fi
	source_f=$1/$1.c
	echo "GEN $source_f"
	cat <<EOF > $source_f
/***************************************************************************
 *                      COPYRIGHT NOTICE
 *             Copyright 2020 Horizon Robotics, Inc.
 *                     All rights reserved.
 ***************************************************************************/

/**
 * @file $1.c
 *
 * @NO{$module_no}
 * @ASIL{B}
 */

#define pr_fmt(fmt)		"[$1]:" fmt

#include "hb_camera_error.h"

#include "camera_log.h"

#include "camera_mod_deserial.h"

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial custom operation: enable link with mask
 *
 * @param[in] deserial_info: deserial module struct
 * @param[in] link_mask: the link mask to 0-disable, 1-enable
 *
 * @return 0:Success, <0:Failure
 */
static int32_t des_link_enable(deserial_info_t *deserial_info, uint8_t link_mask)
{
	int32_t ret = RET_OK;
	cam_info("deserial%d link 0x%x\\n", deserial_info->index, link_mask);

	return ret;
}

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial custom operation: control the remote link bus on/off
 *
 * @param[in] deserial_info: deserial module struct
 * @param[in] link_mask: the link mask to 0-bus off, 1-bus on
 *
 * @return 0:Success, <0:Failure
 */
static int32_t des_remote_control(deserial_info_t *deserial_info, uint8_t link_mask)
{
	int32_t ret = RET_OK;
	cam_info("deserial%d remote 0x%x\\n", deserial_info->index, link_mask);

	return ret;
}

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial custom operation: config mfp gpio function
 *
 * @param[in] deserial_info: deserial module struct
 * @param[in] mfp_mode: the target mode for mfp
 * @param[in] gpio_id: the mfp gpio index to config
 * @param[in] deserial_link: the link to bind for this mfp
 *
 * @return 0:Success, <0:Failure
 */
static int32_t des_mfp_cfg(deserial_info_t *deserial_info, uint8_t mfp_mode, uint8_t gpio_id, uint8_t deserial_link)
{
	int32_t ret = RET_OK;
	cam_info("deserial%d mfp %d mode %d link %d\\n", deserial_info->index, gpio_id, mfp_mode, deserial_link);

	return ret;
}

/**
 * @var deserial_dump_regs
 * deserial dump registers for debug
 */
static const int32_t deserial_dump_regs[] = {
	0x0,
};

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial init operation: keep stream off after done
 *
 * @param[in] deserial_info: deserial module struct
 *
 * @return 0:Success, <0:Failure
 */
static int32_t deserial_init(deserial_info_t *deserial_info)
{
	int32_t ret = RET_OK;
	cam_info("deserial%d i2c%d@0x%02x init\\n", deserial_info->index,
		deserial_info->bus_num, deserial_info->deserial_addr);

	return ret;
}

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial start operation: stream on
 *
 * @param[in] deserial_info: deserial module struct
 * @param[in] port: deserial link port
 *
 * @return 0:Success, <0:Failure
 */
static int32_t deserial_stream_on(deserial_info_t *deserial_info, uint32_t port)
{
	int32_t ret = RET_OK;
	cam_info("deserial%d stream on port %d\\n", deserial_info->index, port);

	return ret;
}

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial stop operation: stream off
 *
 * @param[in] deserial_info: deserial module struct
 * @param[in] port: deserial link port
 *
 * @return 0:Success, <0:Failure
 */
static int32_t deserial_stream_off(deserial_info_t *deserial_info, uint32_t port)
{
	int32_t ret = RET_OK;
	cam_info("deserial%d stream off port %d\\n", deserial_info->index, port);

	return ret;
}

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial deinit operation: restore the status befor init
 *
 * @param[in] deserial_info: deserial module struct
 *
 * @return 0:Success, <0:Failure
 */
static int32_t deserial_deinit(deserial_info_t *deserial_info)
{
	int32_t ret = RET_OK;
	cam_info("deserial%d deinit\\n", deserial_info->index);

	return ret;
}

/**
 * @NO{$module_no}
 * @ASIL{B}
 * @brief deserial deinit operation: restore the status befor init
 *
 * @param[in] deserial_info: deserial module struct
 * @param[out] csi_attr: mipi cst attr struct
 *
 * @return 0:Success, <0:Failure
 */
static int32_t deserial_get_csi_attr(deserial_info_t *deserial_info, csi_attr_t *csi_attr)
{
	int32_t ret = RET_OK;

	return ret;
}

DESERIAL_MAX_MODULE_DF($1, des_link_enable, des_remote_control, des_mfp_cfg, deserial_dump_regs, CAM_MODULE_FLAG_A16D8, NULL);
deserial_module_t $1 = {
	.module = DESERIAL_MNAME($1),
	.init = deserial_init,
	.stream_on = deserial_stream_on,
	.stream_off = deserial_stream_off,
	.deinit = deserial_deinit,
	.get_csi_attr = deserial_get_csi_attr,
};
EOF
}

# do
gen_dir $module

if [ -z "$ver_set" ] || [ ! -f "$module/$makefille_file" ]; then
	gen_makefile $module
fi

gen_version $module

gen_source $module

