/************************************************************************/ /* 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 ¿ØÖÆ */ 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 ¿ØÖÆ*/ //logprint("ctrl sboCtrl free : %s currTime: %5.0f \n",sboCtrl->sbo_var,sGetMsTime()); } return; } #endif /* defined(MVL_UCA) */