/*
* co_network.c - contains multi networking services
*
* Copyright (c) 2012-2023 emotas embedded communication GmbH
*-------------------------------------------------------------------
* $Id: co_network.c 49616 2023-09-26 14:22:08Z boe $
*
*
*-------------------------------------------------------------------
*
*
*/

/********************************************************************/
/**
* \brief multi level networking handling
*
* \file co_network.c
* contains multi level network services
*
*
*/

/* header of standard C - libraries
---------------------------------------------------------------------------*/
#include <stddef.h>

/* header of project specific types
---------------------------------------------------------------------------*/
#include <gen_define.h>

#ifdef CO_NETWORK_ROUTING_CNT
#include <co_datatype.h>
#include <co_timer.h>
#include <co_drv.h>
#include <co_nmt.h>
#include <co_network.h>
#include <co_odaccess.h>
#include "ico_cobhandler.h"
#include "ico_network.h"

/* constant definitions
---------------------------------------------------------------------------*/

/* local defined data types
---------------------------------------------------------------------------*/

/* list of external used functions, if not in headers
---------------------------------------------------------------------------*/

/* list of global defined functions
---------------------------------------------------------------------------*/

/* list of local defined functions
---------------------------------------------------------------------------*/
static CO_INLINE UNSIGNED32	*getNetworkRoutingList(CO_LINE_DECL, UNSIGNED16	idx);

/* external variables
---------------------------------------------------------------------------*/

/* global variables
---------------------------------------------------------------------------*/

/* local defined variables
---------------------------------------------------------------------------*/
static UNSIGNED16	networkId[CO_LINE_ARRAY_DECL];
static UNSIGNED32	networkRoutingList[CO_NETWORK_ROUTING_CNT];
static UNSIGNED8	networkLineCnt[CO_LINE_ARRAY_DECL];
static UNSIGNED16	networkLineOffs[CO_LINE_ARRAY_DECL];

/*
 * line 0

local network: 1

remote network list:
network-id	router-id	line-if

	2			0		1
	3			0		3
	4			0		2

	5			x		1
	6			x		2
	7			x		3
*/


/***************************************************************************/
/**
*
* \brief coNetworkGet - get network interface and router node
*
* Get Network interface und router node for requested destination network
* from object 0x1f2c
*
*/
RET_T coNetworkGet(
		CO_LINE_TYPE	CO_LINE,		/**< can line */
		UNSIGNED16		network,		/**< destination network */
		UNSIGNED8		*pNetworkIf,	/**< network interface number */
		UNSIGNED8		*pRouterNode	/**< router node id */
	)
{
UNSIGNED8	i;
UNSIGNED32	nwRoute;
UNSIGNED8	defaultNetworkIf = 0xffu;
UNSIGNED8	defaultRouterNode = 0xffu;

	/* check all list elements */
	for (i = 0u; i < networkLineCnt[CO_LINE]; i++)  {
		nwRoute = *getNetworkRoutingList(CO_LINE, i);
		/* correct network found ? */
		if ((nwRoute >> 16u) == network)  {
			*pNetworkIf = (UNSIGNED8)(nwRoute & 0xffu);
			*pRouterNode = (UNSIGNED8)((nwRoute >> 8u) & 0xffu);
			return(RET_OK);
		} else {
			/* network = 0 */
			if ((nwRoute >> 16u) == 0u)  {
				defaultNetworkIf = (UNSIGNED8)(nwRoute & 0xffu);
				defaultRouterNode = (UNSIGNED8)((nwRoute >> 8u) & 0xffu);
			}
		}
	}

	/* default route available ? */
	if ((defaultNetworkIf > 0u) && (defaultNetworkIf < 0xffu))  {
		*pNetworkIf = defaultNetworkIf;
		*pRouterNode = defaultRouterNode;
		return(RET_OK);
	}

	return(RET_NETWORK_ID_UNKNOWN);
}


/***************************************************************************/
/**
* \internal
*
* \brief icoNetworkLocal - get local network id
*
*
*
*/
UNSIGNED16 icoNetworkLocalId(
		CO_LINE_TYPE	CO_LINE		/* can line */
	)
{
	return(networkId[CO_LINE]);
}


/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/**
* \internal
*
* \brief icoFlymaGetObjectAddr - get flyma object address
*
* \return none
*
*/
void *icoNetworkGetObjectAddr(
		CO_LINE_TYPE	CO_LINE,		/* can line */
		UNSIGNED16	index,				/* index */
		UNSIGNED8	subIndex			/* subindex */
	)
{
void	*pAddr = NULL;

	switch (index)  {
		case 0x1f2b:
			pAddr = (void *)&networkId[CO_LINE];
			break;

		case 0x1f2c:
			pAddr = (void *)getNetworkRoutingList(CO_LINE, subIndex - 1u);
			break;

		default:
			break;
	}

	return(pAddr);
}


/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/


/***************************************************************************/
/*
* \brief icoErrCtrlVarInit - init error control variables
*
*/
void icoNetworkVarInit(
		CO_CONST UNSIGNED8	*pList		/* line counts */
	)
{
CO_LINE_TYPE	CO_LINE;
UNSIGNED16		offs = 0u;

	for (canLine = 0u; canLine < CO_MULTI_LINE_CNT; canLine++)
	{
		networkLineCnt[CO_LINE] = pList[CO_LINE];
		networkLineOffs[CO_LINE] = offs;
		offs += pList[CO_LINE];
	}
}


/***************************************************************************/
/**
* \internal
*
* \brief
*
* \return none
*
*/
void icoNetworkSetDefaultValue(
		CO_LINE_TYPE	CO_LINE		/* can line */
	)
{
UNSIGNED8	i;
RET_T	retVal;
UNSIGNED16	u16;
UNSIGNED32	u32;


	retVal = coOdGetDefaultVal_u16(CO_LINE, 0x1f2bu, 0u, &u16);
	if (retVal == RET_OK)  {
		networkId[CO_LINE] = u16;
	}

	for (i = 0u; i < networkLineCnt[CO_LINE]; i++)  {
		retVal = coOdGetDefaultVal_u32(CO_LINE, 0x1f2cu, i + 1u, &u32);
		if (retVal == RET_OK)  {
			*getNetworkRoutingList(CO_LINE, i) = u32;
		}
	}
}


static CO_INLINE UNSIGNED32	*getNetworkRoutingList(
		CO_LINE_TYPE	CO_LINE,		/* can line */
		UNSIGNED16	idx				/* index */
	)
{
UNSIGNED32	*rl;

	rl = &networkRoutingList[idx + networkLineOffs[CO_LINE]];

	return(rl);
}
#endif /* CO_NETWORK_ROUTING_CNT */
