/*++
*******************************************************************************
* Copyright (c) 1999-2000 Digi International Inc., All Rights Reserved        *
*                                                                             *
* This software contains proprietary and confidential information of Digi     *
* International Inc.  By accepting transfer of this copy, Recipient agrees    *
* to retain this software in confidence, to prevent disclosure to others,     *
* and to make no use of this software other than that for which it was        *
* delivered.  This is an unpublished copyrighted work of Digi International   *
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly   *
* prohibited.                                                                 *
*                                                                             *
* Restricted Rights Legend                                                    *
*                                                                             *
* Use, duplication, or disclosure by the Government is subject to             *
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in         *
* Technical Data and Computer Software clause at DFARS 252.227-7031 or        *
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -          *
* Restricted Rights at 48 CFR 52.227-19, as applicable.                       *
*                                                                             *
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343          *
*                                                                             *
*******************************************************************************

Module Name:

	FRDataSource.cpp

Abstract:

	Frame Relay Datasource implementation.

Author:

	Michael Zarns

--*/
#include "stdafx.h"
#include "Diagnostic.h"
#include "DataSource.h"
#include "Tracer.h"
#include "IsdnTrace.h"
#include "TraceStatView.h"
#include "Prime.h"
#include "FRDataSource.h"
#include "StatDoc.h"
#include "typeinfo.h"


CFRDataSourceBase::CFRDataSourceBase(const HKEY hkLine, const CString& DeviceName) : 
	CDataSource(hkLine, DeviceName),
	m_LinkStats(m_SNID),
	m_LinkErrors(m_SNID),
	m_LMIStats(m_SNID)
{
	m_Status = dssNotAvailable;
}


void CFRDataSourceBase::LoadSummaryInfo(const CString& frmvsn)
{
	CDataSource::LoadSummaryInfo(frmvsn);
	AddDriverInfo(c_pszKeyFR_PVC_ServiceName);
}

const CSXB_USER_IOCTL *CFRDataSourceBase::GetStatType(const type_info& Type, int index) const
{
	const CSXB_USER_IOCTL *result = CDataSource::GetStatType(Type, index);

	if (result == NULL) 
	{
		if (typeid(m_LinkErrors) == Type)
			result = &m_LinkErrors;
		else if (typeid(m_LinkStats) == Type)
			result = &m_LinkStats;
		else if (typeid(m_LMIStats) == Type)
			result = &m_LMIStats;
		else if (typeid(CFR_PROTOCOL_ERRORS) == Type)
			result = m_ProtocolErrors[index];
		else if (typeid(CFR_PLL_STATS) == Type)
			result = m_PllStats[index];
		else if (typeid(CFR_INJ_MANG) == Type)
			result = m_InjManager[index];
	}
	return result;
}


BOOL CFRDataSourceBase::UpdateDataSourceStats()
{
	GetData(&m_LinkStats);

	if (GetData(&m_LinkErrors) == dssRunning)
		IncrementError(m_Err, m_LinkErrors->rcvframe_inv +
													m_LinkErrors->rcvinv_short +
													m_LinkErrors->rcvinv_long +
													m_LinkErrors->rcvinv_dlci +
													m_LinkErrors->rcvunk_dlci);

	if (m_LMIType != lmiNone && GetData(&m_LMIStats) == dssRunning)
		IncrementError(m_Err, m_LMIStats->lmi_inv_msg_rcvd + m_LMIStats->lmi_no_ie_rep_type +
													m_LMIStats->lmi_no_ie_keep_alive + m_LMIStats->lmi_lost_seq_num +
													m_LMIStats->lmi_stat_resp_timeout + m_LMIStats->lmi_unsupp_ie_msg +
													m_LMIStats->lmi_unexpected_pvc_num + m_LMIStats->lmi_unexpected_pvc_stat_msg);

	for (short i = 0; m_Status == dssRunning && i < GetNumCircuits(); i++)
		GetData(m_PllStats[i]);

	for (i = 0; m_Status == dssRunning && i < GetNumCircuits(); i++)
		GetData(m_InjManager[i]);

	for (i = 0; m_Status == dssRunning && i < GetNumCircuits(); i++)
		if (GetData(m_ProtocolErrors[i]) == dssRunning)
			IncrementError(m_Err, (*m_ProtocolErrors[i])->rcv_unkprot +
														(*m_ProtocolErrors[i])->rcv_unkframe +
														(*m_ProtocolErrors[i])->rcv_lostframe +
														(*m_ProtocolErrors[i])->rcv_unkorg);

	return m_Status == dssRunning;
}


void CFRDataSourceBase::LoadConfigCircuits()
{
	// Construct the FRService Key for this line

	HKEY hFrService;
	TRACE("LoadConfigCircuits:m_ParameterRegPath = %s\n",m_ParameterRegPath);
	CString strFrService = m_ParameterRegPath  + 
						   CString("\\") + CString(DXB_REGVAL_LINE_SERVICE_FR) +
						   CString("\\") + m_LineNumber;
	TRACE("LoadConfigCircuits:strFrService = %s\n",strFrService);
 	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
		             strFrService,
					 &hFrService) == ERROR_SUCCESS) {
		char KeyName[256];
		DWORD NameSize = 256, i = 0;
		FILETIME time;

		while (RegEnumKeyEx(hFrService, i++, KeyName, &NameSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) {

			NameSize = 256;
			TRACE("LoadConfigCircuits:FRService = %s\n",KeyName);

			HKEY hPVC;
			RegOpenKeyEx(hFrService, KeyName , &hPVC);

				DWORD dlci;
				RegGetDWord(hPVC, c_pszValueDLCI, &dlci);
				m_Circuits.Add(dlci);

				RegCloseKey(hPVC);
		}
		RegCloseKey(hFrService);
	}

	CString path =	m_RegPath + _T('\\') + c_pszKeyFR_ProtocolMain;
 	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, &hFrService) != ERROR_SUCCESS)
		return;

	DWORD lmiflags;
	RegGetDWord(hFrService, c_pszValueFlags, &lmiflags);

	RegCloseKey(hFrService);

	if ((lmiflags & FRS_LINK_FLAGS_LMI_REV1) > 0)
		m_LMIType = lmiRevision1;
	else if ((lmiflags & FRS_LINK_FLAGS_GANG_OF_4) > 0)
		m_LMIType = lmiStrataCom;
	else if ((lmiflags & FRS_LINK_FLAGS_ANNEX_D) > 0)
		m_LMIType = lmiAnnexD;
	else if ((lmiflags & FRS_LINK_FLAGS_ANNEX_A) > 0)
		m_LMIType = lmiAnnexA;
	else
		m_LMIType = lmiNone;
	
	m_ProtocolErrors.RemoveAll();
	m_PllStats.RemoveAll();
	m_InjManager.RemoveAll();

	for (short i = 0; i < GetNumCircuits(); i++) {
		m_ProtocolErrors.Add(new CFR_PROTOCOL_ERRORS(m_SNID, GetCircuitNum(i)));
		m_PllStats.Add(new CFR_PLL_STATS(m_SNID, GetCircuitNum(i)));
		m_InjManager.Add(new CFR_INJ_MANG(m_SNID, GetCircuitNum(i)));
		}
}


CTracer *CFRDataSourceBase::CreateTracer()
{ return new CFRTracer(this); };


CTraceData *CFRDataSourceBase::CreateTraceData(DWORD baud, CDWordArray& circuits)
{ return new CFRTraceData(baud, circuits); };


//------------------------------------------------------------ MLZ 4/15/2000 {
CFRDataSource::CFRDataSource(const HKEY hkLine, const CString& DeviceName) : 
	CFRDataSourceBase(hkLine, DeviceName)
{
	m_Status = dssNotAvailable;
}

CRuntimeClass *CFRDataSource::GetStatDocClass() const
{
	return RUNTIME_CLASS(CFRStatDoc);
}

BOOL CFRDataSource::UpdateDataSourceStats()
{
	if (CDataSource::UpdateDataSourceStats())
		CFRDataSourceBase::UpdateDataSourceStats();
	
	HandleClearStats(m_Err, m_ClearErr);
	return m_Status == dssRunning;
}

void CFRDataSource::LoadConfigCircuits()
{
	CDataSource::LoadConfigCircuits();
	CFRDataSourceBase::LoadConfigCircuits();
}


///////////////////////////////////////////////////////////////////////////////
//
// CFRCsuDataSource
//
///////////////////////////////////////////////////////////////////////////////

CFRCsuDataSource::CFRCsuDataSource(const HKEY hkLine, const CString& DeviceName) : 
	CFRDataSourceBase(hkLine, DeviceName),
	m_IfaceState(m_SNID - 'A'),
	m_Rfc1406(m_SNID - 'A')
{
	m_Status = dssNotAvailable;
}

CRuntimeClass *CFRCsuDataSource::GetStatDocClass() const
{
	return RUNTIME_CLASS(CFRCsuStatDoc);
}

const CSXB_USER_IOCTL *CFRCsuDataSource::GetStatType(const type_info& Type, int index) const
{
	const CSXB_USER_IOCTL *result = CFRDataSourceBase::GetStatType(Type, index);

	if (result == NULL) 
	{
		if (typeid(m_IfaceState) == Type)
			result = &m_IfaceState;
		else if (typeid(m_Rfc1406) == Type)
			result = &m_Rfc1406;
	}
	return result;
}

BOOL CFRCsuDataSource::UpdateDataSourceStats()
{
	if (CFRDataSourceBase::UpdateDataSourceStats()) 
	{
		GetData(&m_IfaceState);
		if ( m_Status == dssRunning )
		{
			switch ( ALARM_CONDITION( m_IfaceState->State ) )
			{
				case RED_ALARM_CONDITION:		m_Alarms = "Red";		break;
				case YELLOW_ALARM_CONDITION:	m_Alarms = "Yellow";	break;
				case BLUE_ALARM_CONDITION:		m_Alarms = "Blue";	break;
				case NO_ALARM_CONDITION:		
				default:								m_Alarms = "None";	break;
			}
		}
		else
			m_Alarms = "N/A";

		GetData(&m_Rfc1406);
		if ( m_Status == dssRunning )
		{
			// Add up the 24hour total errors
			__int64 Error = 
				m_Rfc1406->Total.ES + m_Rfc1406->Total.SES + m_Rfc1406->Total.SEFS + 
				m_Rfc1406->Total.UAS + m_Rfc1406->Total.CSS + m_Rfc1406->Total.PCV +
				m_Rfc1406->Total.LES + m_Rfc1406->Total.BES + m_Rfc1406->Total.DM + 
				m_Rfc1406->Total.LCV;
			// Then add in the current 15-minute interval errors
			Error += 
				m_Rfc1406->Current.ES + m_Rfc1406->Current.SES + m_Rfc1406->Current.SEFS + 
				m_Rfc1406->Current.UAS + m_Rfc1406->Current.CSS + m_Rfc1406->Current.PCV +
				m_Rfc1406->Current.LES + m_Rfc1406->Current.BES + m_Rfc1406->Current.DM + 
				m_Rfc1406->Current.LCV;
			m_Err = Error;	// Don't increment because these counters are already cumulative
		}
	}

	HandleClearStats(m_Err, m_ClearErr);
	return m_Status == dssRunning;
}

void CFRCsuDataSource::LoadConfigCircuits()
{
	CFRDataSourceBase::LoadConfigCircuits();
}

