353 lines
12 KiB
C
353 lines
12 KiB
C
/************************************************************************/
|
||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||
/************************************************************************/
|
||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||
/* 1998-2004, All Rights Reserved. */
|
||
/* */
|
||
/* PROPRIETARY AND CONFIDENTIAL */
|
||
/* */
|
||
/* MODULE NAME : mvlu_sbo.c */
|
||
/* PRODUCT(S) : MMSEASE */
|
||
/* */
|
||
/* MODULE DESCRIPTION : */
|
||
/* */
|
||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||
/* */
|
||
/* MODIFICATION LOG : */
|
||
/* Date Who Rev Comments */
|
||
/* -------- --- ------ ------------------------------------------- */
|
||
/* 05/06/08 JRB 15 Chg sbo_pool from static to global. */
|
||
/* 02/26/07 JRB 14 initSboCtrl: add use_ms_timer arg. */
|
||
/* 01/27/05 JRB 13 Log if createSboName fails. */
|
||
/* 12/03/04 JRB 12 Move 61850 code to new module mvl61850_ctl.c.*/
|
||
/* Make initSboCtrl funct global so 61850 */
|
||
/* module can use it too. */
|
||
/* Use strrchr to find last '$'. */
|
||
/* 09/20/04 JRB 11 Replace chk_sbo_select w/ mvlu_sbo_chk_state.*/
|
||
/* Chg chk_sbo_timeouts to mvlu_sbo_chk_timers. */
|
||
/* Do timeouts ONLY in mvlu_sbo_chk_timers. */
|
||
/* Do "Select" only if SBO is ONLY attribute */
|
||
/* being read (not part of higher level var). */
|
||
/* Add funct mvlu_sbo_ctrl_free. */
|
||
/* Del currTime global variable. */
|
||
/* Pass sboTimeout arg to initSboCtrl. */
|
||
/* 12/11/02 JRB 10 Use new mvl_uca.h */
|
||
/* 12/09/02 MDE 09 Changed SBO reference handling */
|
||
/* 10/25/00 JRB 08 Add #ifdef MVL_UCA. */
|
||
/* 07/13/00 JRB 07 Add #ifdef USE_RT_TYPE_2. */
|
||
/* 09/13/99 MDE 06 Added SD_CONST modifiers */
|
||
/* 09/07/99 MDE 05 Changed MVL_VA_SCOPE to MVL_SCOPE */
|
||
/* 12/11/98 MDE 04 Removed scope references from VA */
|
||
/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */
|
||
/* 09/21/98 MDE 02 Minor lint cleanup */
|
||
/* 09/11/98 MDE 01 New */
|
||
/************************************************************************/
|
||
|
||
#include "glbtypes.h"
|
||
#include "sysincs.h"
|
||
#include "glbsem.h"
|
||
#include "mmsdefs.h"
|
||
#include "mvl_uca.h"
|
||
#include "mvl_log.h"
|
||
|
||
#if defined(MVL_UCA) /* This entire module is only valid for UCA. */
|
||
|
||
/************************************************************************/
|
||
/* For debug version, use a static pointer to avoid duplication of */
|
||
/* __FILE__ strings. */
|
||
|
||
#ifdef DEBUG_SISCO
|
||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||
#endif
|
||
|
||
/************************************************************************/
|
||
/* Global variables */
|
||
/************************************************************************/
|
||
|
||
MVL_SBO_CTRL sbo_pool[MAX_NUM_SBO_PEND];
|
||
|
||
/************************************************************************/
|
||
/* Static functions */
|
||
|
||
static ST_VOID createSboName (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope,
|
||
ST_CHAR *dest,
|
||
ST_BOOLEAN select, ST_RTREF primRef);
|
||
|
||
/************************************************************************/
|
||
/************************************************************************/
|
||
/* mvlu_sbo_select_rd_ind */
|
||
/* Leaf function for reading UCA "SBO" attribute (i.e. performing */
|
||
/* Control Model 'Select' Service). */
|
||
/* NOTE: do NOT use this leaf function for IEC 61850 SBO. */
|
||
/************************************************************************/
|
||
|
||
ST_VOID mvlu_sbo_select_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl)
|
||
{
|
||
ST_CHAR *dest;
|
||
MVL_VAR_ASSOC *va;
|
||
MVL_SCOPE *va_scope;
|
||
ST_CHAR sboName[MAX_SBO_NAME_SIZE+1];
|
||
MVL_SBO_CTRL *sboCtrl;
|
||
ST_CHAR *lastdollar; /* ptr to last '$' in var name */
|
||
|
||
/* First take care of timeout housekeeping */
|
||
mvlu_sbo_chk_timers ();
|
||
|
||
/* find the name of the attribute being selected */
|
||
va = mvluRdVaCtrl->rdVaCtrl->va;
|
||
|
||
/* Only perform "Select" if SBO is ONLY attribute being read. */
|
||
/* Check this by seeing if variable name ends with "$SBO". */
|
||
/* Point to where "$SBO" should be, then see if it's there. */
|
||
lastdollar = strrchr (va->name, '$'); /* find last '$' */
|
||
if (lastdollar != NULL && strcmp (lastdollar+1, "SBO") == 0)
|
||
{
|
||
va_scope = &mvluRdVaCtrl->rdVaCtrl->va_scope;
|
||
createSboName (va, va_scope, sboName, SD_TRUE, mvluRdVaCtrl->primRef);
|
||
|
||
/* Get a SBO control element */
|
||
sboCtrl = initSboCtrl (mvluRdVaCtrl->indCtrl->event->net_info,sboName,
|
||
SBO_SELECT_TIMEOUT, SD_FALSE); /* timeout in seconds*/
|
||
if (sboCtrl == NULL)
|
||
{
|
||
mvlu_rd_prim_done (mvluRdVaCtrl, SD_FAILURE);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
/* Higher level variable read. Allow read, but just return NULL (empty) string.*/
|
||
sboName[0]='\0';
|
||
|
||
dest = (ST_CHAR *) mvluRdVaCtrl->primData;
|
||
strcpy (dest, sboName);
|
||
mvlu_rd_prim_done (mvluRdVaCtrl, SD_SUCCESS);
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* mvlu_sbo_operate_wr_ind */
|
||
/* NOTE: this leaf function should be used only for UCA (not for 61850).*/
|
||
/************************************************************************/
|
||
|
||
ST_VOID mvlu_sbo_operate_wr_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl)
|
||
{
|
||
MVL_SBO_CTRL *sboSelect;
|
||
MVL_SCOPE *va_scope;
|
||
ST_CHAR sboName[MAX_SBO_NAME_SIZE+1];
|
||
|
||
/* First take care of timeout housekeeping */
|
||
mvlu_sbo_chk_timers ();
|
||
|
||
va_scope = &mvluWrVaCtrl->wrVaCtrl->va_scope;
|
||
createSboName (mvluWrVaCtrl->wrVaCtrl->va, &mvluWrVaCtrl->wrVaCtrl->va_scope, sboName, SD_FALSE, (ST_RTREF) 0);
|
||
sboSelect = mvlu_sbo_chk_state (sboName,
|
||
mvluWrVaCtrl->indCtrl->event->net_info);
|
||
if (sboSelect != NULL)
|
||
{
|
||
u_mvl_sbo_operate (sboSelect, mvluWrVaCtrl);
|
||
sboSelect->in_use = SD_FALSE;
|
||
}
|
||
else /* The select was not in place, cannot operate ... */
|
||
{
|
||
mvlu_wr_prim_done (mvluWrVaCtrl, SD_FAILURE);
|
||
}
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* mvlu_clr_pend_sbo */
|
||
/************************************************************************/
|
||
|
||
ST_VOID mvlu_clr_pend_sbo (MVL_NET_INFO *net_info)
|
||
{
|
||
ST_INT i;
|
||
|
||
for (i = 0; i < MAX_NUM_SBO_PEND; ++i)
|
||
{
|
||
if (sbo_pool[i].net_info == net_info)
|
||
sbo_pool[i].in_use = SD_FALSE;
|
||
}
|
||
}
|
||
|
||
/************************************************************************/
|
||
/************************************************************************/
|
||
/************************************************************************/
|
||
/* mvlu_sbo_chk_timers */
|
||
/************************************************************************/
|
||
|
||
ST_VOID mvlu_sbo_chk_timers ()
|
||
{
|
||
ST_INT i;
|
||
MVL_SBO_CTRL *sboCtrl;
|
||
time_t currTime;
|
||
ST_DOUBLE currTimeMs; /* current time in milliseconds */
|
||
|
||
currTime = time (NULL); /* PORT ISSUE: time() */
|
||
currTimeMs = sGetMsTime ();
|
||
sboCtrl = sbo_pool;
|
||
for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl)
|
||
{
|
||
if (sboCtrl->in_use == SD_TRUE)
|
||
{
|
||
if (sboCtrl->use_ms_timer)
|
||
{
|
||
if (sboCtrl->expire_time_ms < currTimeMs)
|
||
sboCtrl->in_use = SD_FALSE; /* SBO timer expired */
|
||
}
|
||
else /* use timer in seconds */
|
||
{
|
||
if (sboCtrl->expire_time < currTime)
|
||
sboCtrl->in_use = SD_FALSE; /* SBO timer expired */
|
||
}
|
||
/* renxiaobao <20><><EFBFBD><EFBFBD> */
|
||
if (sboCtrl->in_use != SD_TRUE)
|
||
printf("sboCtrl TimeOut : %s currTime: %5.0f \n",sboCtrl->sbo_var,sGetMsTime());
|
||
}
|
||
}
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* initSboCtrl */
|
||
/************************************************************************/
|
||
|
||
MVL_SBO_CTRL *initSboCtrl (MVL_NET_INFO *net_info,
|
||
ST_CHAR *sbo_name,
|
||
ST_UINT32 sboTimeout,
|
||
ST_BOOLEAN use_ms_timer)
|
||
{
|
||
ST_INT i;
|
||
MVL_SBO_CTRL *sboCtrl;
|
||
time_t currTime = time (NULL);
|
||
|
||
/* OK, now see if the element is already selected */
|
||
sboCtrl = sbo_pool;
|
||
for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl)
|
||
{
|
||
if (sboCtrl->in_use == SD_TRUE && !strcmp (sboCtrl->sbo_var, sbo_name))
|
||
{
|
||
/* OK, already selected, make sure it is us then reset the timeout */
|
||
if (sboCtrl->net_info != net_info)
|
||
return (NULL);
|
||
|
||
if (sboCtrl->use_ms_timer)
|
||
sboCtrl->expire_time_ms = sGetMsTime () + sboTimeout;
|
||
else
|
||
sboCtrl->expire_time = currTime + sboTimeout;
|
||
return (sboCtrl);
|
||
}
|
||
}
|
||
|
||
/* The protected element is not selected, find a unused SBO control */
|
||
sboCtrl = sbo_pool;
|
||
for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl)
|
||
{
|
||
if (sboCtrl->in_use == SD_FALSE)
|
||
break;
|
||
}
|
||
if (i >= MAX_NUM_SBO_PEND)
|
||
return (NULL);
|
||
|
||
/* OK, we have a newly selected SBO control, set the parameters */
|
||
sboCtrl->in_use = SD_TRUE;
|
||
sboCtrl->use_ms_timer = use_ms_timer;
|
||
if (sboCtrl->use_ms_timer)
|
||
sboCtrl->expire_time_ms = sGetMsTime () + sboTimeout;
|
||
else
|
||
sboCtrl->expire_time = currTime + sboTimeout;
|
||
sboCtrl->net_info = net_info;
|
||
strcpy (sboCtrl->sbo_var, sbo_name);
|
||
return (sboCtrl);
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* mvlu_sbo_chk_state */
|
||
/* Find the MVL_SBO_CTRL struct for this "sboName". */
|
||
/* Call createSboName (for UCA), mvl61850_sbo_create_sboname (for 61850)*/
|
||
/* to generate the "sboName" string to pass to this function. */
|
||
/************************************************************************/
|
||
|
||
MVL_SBO_CTRL *mvlu_sbo_chk_state (ST_CHAR *sboName,
|
||
MVL_NET_INFO *net_info)
|
||
{
|
||
ST_INT i;
|
||
MVL_SBO_CTRL *sboCtrl;
|
||
|
||
/* See if we have selected the element */
|
||
sboCtrl = sbo_pool;
|
||
for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl)
|
||
{
|
||
if (sboCtrl->in_use == SD_TRUE &&
|
||
!strcmp (sboCtrl->sbo_var, sboName) &&
|
||
sboCtrl->net_info == net_info)
|
||
{
|
||
return (sboCtrl);
|
||
}
|
||
}
|
||
return (NULL);
|
||
}
|
||
|
||
/************************************************************************/
|
||
/************************************************************************/
|
||
/* createSboName */
|
||
/* Creates a name to return when an UCA SBO attribute is read. */
|
||
/* NOTE: this name may also be passed to "mvlu_sbo_chk_state" */
|
||
/* to find the correct MVL_SBO_CTRL struct. */
|
||
/************************************************************************/
|
||
static ST_VOID createSboName (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope,
|
||
ST_CHAR *dest, ST_BOOLEAN select, ST_RTREF primRef)
|
||
{
|
||
ST_INT len;
|
||
|
||
/* if primRef is NULL, then don't perform the string table lookup */
|
||
switch (va_scope->scope)
|
||
{
|
||
case VMD_SPEC:
|
||
strcpy (dest, "/");
|
||
break;
|
||
|
||
case DOM_SPEC:
|
||
strcpy (dest, va_scope->dom->name);
|
||
strcat (dest, "/");
|
||
break;
|
||
|
||
case AA_SPEC:
|
||
strcpy (dest,"@/");
|
||
break;
|
||
}
|
||
|
||
/* Scope in place, now append the name of variable */
|
||
strcat (dest, va->name);
|
||
|
||
/* Now, "SBO" is the end of the name, and the reference is the index */
|
||
/* to the string for the component that is being selected. So, if we */
|
||
/* want the name of the protected element we just replace the "SBO" */
|
||
/* with the element name. */
|
||
if (select == SD_TRUE)
|
||
{
|
||
len = strlen (dest) - 3;
|
||
|
||
if (primRef != 0)
|
||
/* primRef must be a pointer to a string; name of protected element */
|
||
strcpy (&dest[len], (ST_CHAR *) primRef);
|
||
else
|
||
MVL_LOG_ERR1 ("SBO name generated '%s' is invalid", dest);
|
||
/* DEBUG: should this function return SD_FAILURE in this case? */
|
||
}
|
||
}
|
||
/************************************************************************/
|
||
/* mvlu_sbo_ctrl_free */
|
||
/* Frees the MVL_SBO_CTRL struct by setting in_use=SD_FALSE. */
|
||
/* Client must "Select" (i.e. read SBO) again before next "Operate". */
|
||
/************************************************************************/
|
||
void logprint(char * fmt,...);
|
||
ST_VOID mvlu_sbo_ctrl_free (MVL_SBO_CTRL *sboCtrl)
|
||
{
|
||
/* When writing non-SBO variables, sboCtrl == NULL. */
|
||
if (sboCtrl)
|
||
{
|
||
sboCtrl->in_use = SD_FALSE;
|
||
/*renxiaobao <20><><EFBFBD><EFBFBD>*/
|
||
//logprint("ctrl sboCtrl free : %s currTime: %5.0f \n",sboCtrl->sbo_var,sGetMsTime());
|
||
}
|
||
return;
|
||
}
|
||
#endif /* defined(MVL_UCA) */
|