/*++
*******************************************************************************
* Copyright (c) 1990-98 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:

   houston.cpp

Abstract:

   Houston adapter specific data source.

Author:

   Michael Zarns

--*/
#include "stdafx.h"
#include "Diagnostic.h"
#include "DataSource.h"
#include "DiagDoc.h"
#include "StatDoc.h"

#include "SessionStatView.h"
#include "FRLineStatView.h"
#include "LAPBLineView.h"
#include "X25LineStatView.h"
#include "FRVCStatView.h"
#include "X25VCStatView.h"
#include "SummaryDlg.h"
#include "filter.h"

#include "Tracer.h"
#include "IsdnTrace.h"
#include "TraceStatView.h"
#include "hlc.h"
#include <typeInfo.h>

void CHlcDataSource::LoadSummaryInfo(const CString& frmvsn)
{
	CDataSource::LoadSummaryInfo(frmvsn);
	AddDriverInfo("DigiIsdn");
	AddDriverInfo("DigiAsyn");
	AddDriverInfo("DigiPci");
}

CHlcDataSource::CHlcDataSource(const HKEY hkLine, const CString& DeviceName, const CString& Protocol) : 
	CDataSource(hkLine, DeviceName),
	m_Ds1Status(m_SNID),
	m_Ds1ExtStatus(m_SNID),
	m_BriStatus(m_SNID),
	m_BriConfig(m_SNID),
	m_DChanExtStatus(m_SNID)
{
	m_Status = dssNotAvailable;
	m_Protocol = Protocol;
	m_ModemStart = 0;
	m_ModemCount = 0;
	m_IsDs1    = FALSE;
	m_IsIsdn   = FALSE;
	m_IsModems = FALSE;
	m_IsBri    = FALSE;
}


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

	if ( Type == typeid(CDS1_STATUS) )
		result = &m_Ds1Status;
	else if ( Type == typeid(CDS1_EXT_STATUS) )
		result = &m_Ds1ExtStatus;
	else if ( Type == typeid(CBRI_STATUS) )
		result = &m_BriStatus;
	else if ( Type == typeid(CMODEM_STATUS) )
		result = m_ModemStatus[index];
	else if ( Type == typeid(CMODEM_EXT_STATUS) )
		result = m_ModemExtStatus[index];
	else if ( Type == typeid(CDCHAN_EXT_STATUS) )
		result = &m_DChanExtStatus;
	else if ( Type == typeid(CBRI_CONFIG) )
		result = &m_BriConfig;
	else
		result = NULL;

	return result;
}

BOOL CHlcDataSource::UpdateDataSourceStats()
{
	if ( m_IsDs1 && m_Status == dssRunning )
	{
		GetData(&m_Ds1Status);

		if ( m_Status == dssRunning )
		{
			// FIXME, FIXME!  Duplicated code from statview.cpp.
			switch ( m_Ds1Status->alarm )
			{
				case DS1_RED_ALARM:		m_Alarms = "Red";		break;
				case DS1_BLUE_ALARM:		m_Alarms = "Blue";	break;
				case DS1_YELLOW_ALARM:	m_Alarms = "Yellow";	break;
				case DS1_NO_ALARM:		
				default:						m_Alarms = "None";	break;
			}
		}
		else
			m_Alarms = "N/A";

		GetData(&m_Ds1ExtStatus);
		if ( m_Status == dssRunning )
		{
			__int64 Error = 
				m_Ds1ExtStatus->errored_seconds + m_Ds1ExtStatus->unavailable_seconds +
				m_Ds1ExtStatus->bursty_seconds + m_Ds1ExtStatus->severe_seconds +
				m_Ds1ExtStatus->severe_framing_seconds + m_Ds1ExtStatus->controlled_slip_seconds + 
				m_Ds1ExtStatus->loss_of_frame_count + m_Ds1ExtStatus->degraded_minutes +
				m_Ds1ExtStatus->line_errored_seconds + m_Ds1ExtStatus->line_code_violations +
				m_Ds1ExtStatus->crc_error_count;
			m_Err = Error;	// Don't increment because these counters are already cumulative
		}
	}

	if ( m_IsBri && m_Status == dssRunning )
	{
		GetData(&m_BriStatus);
		if ( m_Status == dssRunning )
		{
			__int64 Error = m_BriStatus->loss_of_sync + m_BriStatus->collisions;
			m_Err = Error;	// Don't increment because these counters are already cumulative
		}
		GetData(&m_BriConfig);
		GetData(&m_DChanExtStatus);
	}	

	if ( m_IsModems )
	{
		for (short i = 0; i < GetNumCircuits(); i++)
		{
			if ( m_Status == dssRunning )
				GetData(m_ModemStatus[i]);
			CMODEM_STATUS* pModem = m_ModemStatus[i];
			pModem;
		}

#if 0
		for (i = 0; i < GetNumCircuits(); i++)
		{
			if ( m_Status == dssRunning )
				GetData(m_ModemExtStatus[i]);
			CMODEM_EXT_STATUS* pModemExt = m_ModemExtStatus[i];
			pModemExt;
		}
#endif
	}

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

void CHlcDataSource::AddModems( ULONG count )
{
	m_ModemStart = (m_SNID - DXB_REGVAL_LINE_SNID_ENUM_FIRST) * count;
	m_ModemCount = count;

	m_ModemStatus.RemoveAll();
	m_ModemExtStatus.RemoveAll();

	for (ULONG i = 0; i < m_ModemCount; i++) 
	{
		m_Circuits.Add(i);
		m_ModemStatus.Add( new CMODEM_STATUS( m_ModemStart + i ) );
//		m_ModemExtStatus.Add( new CMODEM_EXT_STATUS( m_ModemStart + i ) );
	}
}


///////////////////////////////////////////////////////////////////////////////
//
// Houston (PRI)
//

CHlcPriDataSource::CHlcPriDataSource(const HKEY hkLine, const CString& DeviceName, const CString& Protocol, ULONG iLine ) : 
	CHlcDataSource(hkLine, DeviceName, Protocol)
{
	CString E1( DXB_REGVAL_PROTOCOL_ENUM_E1 );
	ULONG nChannels = Protocol == E1 ? 30 : 23;

#ifdef NFAS_ON
#pragma message( "Compiling in NFAS support" )
	// When NFAS is turned on, the second line has one extra bchannel, T1 only!
	if ( iLine == 1 && Protocol != E1 )
	{
		ULONG nfas;
		HKEY hkDs1;
		LONG Success = RegOpenKeyEx(hkLine, DXB_REGKEY_DS1, &hkDs1);
		if ( Success == ERROR_SUCCESS )
		{
			Success = RegGetDWord( hkLine, DXB_REGVAL_DS1_NFAS, &nfas );
			if ( Success == ERROR_SUCCESS && nfas == NFAS_ON )
					nChannels += 1;	
			RegCloseKey(hkDs1);
		}
	}
#endif
	
	m_Channels = nChannels;
	m_IsDs1    = TRUE;
	m_IsIsdn   = TRUE;
	m_IsE1R2   = TRUE;
	m_IsModems = TRUE;
	m_BaudRate = 64000;	// Baudrate is for d-channel trace.  PRI D-channel is always 64000 bps.
}

CTracer *CHlcPriDataSource::CreateTracer()
{ 
	return new CIsdnTracer(this); 
}


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

///////////////////////////////////////////////////////////////////////////////
//
// Houston (E1R2)
//

CHlcE1R2DataSource::CHlcE1R2DataSource(const HKEY hkLine, const CString& DeviceName, const CString& Protocol, ULONG iLine ) : 
	CHlcDataSource(hkLine, DeviceName, Protocol)
{
	CString E1R2( DXB_REGVAL_PROTOCOL_ENUM_E1R2 );
	ULONG nChannels = Protocol == E1R2 ? 30 : 23;

#ifdef NFAS_ON
#pragma message( "Compiling in NFAS support" )
	// When NFAS is turned on, the second line has one extra bchannel, T1 only!
	if ( iLine == 1 && Protocol != E1R2 )
	{
		ULONG nfas;
		HKEY hkDs1;
		LONG Success = RegOpenKeyEx(hkLine, DXB_REGKEY_DS1, &hkDs1);
		if ( Success == ERROR_SUCCESS )
		{
			Success = RegGetDWord( hkLine, DXB_REGVAL_DS1_NFAS, &nfas );
			if ( Success == ERROR_SUCCESS && nfas == NFAS_ON )
					nChannels += 1;	
			RegCloseKey(hkDs1);
		}
	}
#endif
	
	m_Channels = nChannels;
	m_IsDs1    = TRUE;
	m_IsE1R2   = TRUE;
	m_IsModems = TRUE;
	m_BaudRate = 64000;	// Baudrate is for d-channel trace.
}

CTracer *CHlcE1R2DataSource::CreateTracer()
{ 
	return new CIsdnTracer(this); 
}


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

///////////////////////////////////////////////////////////////////////////////
//
// Houston (Channelized T1)
//

CHlcCt1DataSource::CHlcCt1DataSource(const HKEY hkLine, const CString& DeviceName, const CString& Protocol) : 
	CHlcDataSource(hkLine, DeviceName, Protocol)
{
	m_Channels = 24;
	m_IsDs1    = TRUE;
	m_IsModems = TRUE;
	m_BaudRate = 0;	// BaudRate is for trace.  No d-channel, no trace ==> no baudrate
}

CTracer *CHlcCt1DataSource::CreateTracer()
{ 
	return NULL;
}


CTraceData *CHlcCt1DataSource::CreateTraceData(DWORD baud, CDWordArray& circuits)
{
	return NULL;
}


///////////////////////////////////////////////////////////////////////////////
//
// London (BRI)
//

CHlcBriDataSource::CHlcBriDataSource(const HKEY hkLine, const CString& DeviceName, const CString& Protocol) : 
	CHlcDataSource(hkLine, DeviceName, Protocol)
{
	m_Channels = 2;
	m_IsIsdn   = TRUE;
	m_IsModems = TRUE;
	m_IsBri    = TRUE;
	m_BaudRate = 8000;	// Baudrate is for d-channel trace.  BRI D-channel is always 8000 bps.
}

CTracer *CHlcBriDataSource::CreateTracer()
{ 
	return new CIsdnTracer(this); 
}


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


///////////////////////////////////////////////////////////////////////////////
//
// Chaska (Modems)
//

CHlcModemDataSource::CHlcModemDataSource(const HKEY hkLine, const CString& DeviceName, const CString& Protocol) : 
	CHlcDataSource(hkLine, DeviceName, Protocol)
{
	m_Channels = 1;
	m_IsModems = TRUE;
	m_BaudRate = 0;	// BaudRate is for trace.  No d-channel, no trace ==> no baudrate
}

CTracer *CHlcModemDataSource::CreateTracer()
{ 
	return new CIsdnTracer(this); 
}


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