/*
 * ++
 * 
****************************************************************************
 * 
 *
 * This software contains proprietary and confiential 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.                                                              * *
 * 
****************************************************************************
 * 
 * 
 * Module Name:
 * 
 * xstat.c
 * 
 * Abstract:
 * 
 * This module contains the main portion of a program which is used to test and
 * manipulate a DigiBoard X25 controller.
 * 
 * Revision History:
 * 
 * $Log$
 * 
 * -- */

#include <stdio.h>
#include <stdlib.h>

#include <windows.h>
#include <assert.h>

// Stream specific include files
#include <sys\types.h>
#include <sys\snet\uint.h>
#include <sys\stropts.h>

// #define MAXIOCBSZ   1024    /* max ioctl data block size */
#include <sys\stream.h>

// Spider Streams specific include files
#include <sys\snet\alloc.h>
#include <sys\snet\sxbus.h>

#include <sys\snet\dgatlas.h>
#include <sys\snet\dgpri.h>

#include <il3_lmi.h>

#include <sys/snet/isdn_proto.h>
#include <sys/snet/il3_config.h>
#include <sys/snet/lapd_control.h>
#include <sys/snet/iwan_control.h>

#include <sys/snet/m32.h>

#include <sxbioctl.h>


#define	MAX_SNID_LEN	4
#define NO_SNID_CHANNELS 23

#define VALID_OPTIONS "zgc:i:l:w:?"

 /*
  * Protocols recognised by the utilities.
  */
#define IL3_PROTO		0x02
#define LAPD_PROTO		0x04
#define IWAN_PROTO		0x08

int             getopt(int argc, char **argv, char *opts);
extern char    *optarg;
extern int      optind;

int             StrToWStr(LPWSTR wszDest, LPSTR szSrc, LONG count);
USHORT          WstrLength(IN PWSTR Wstr);

void            show_LAPD_stats(HANDLE hFile, UCHAR subnet, int global);
void            reset_LAPD_stats(HANDLE hFile, UCHAR subnet, int global);

void            reset_IWAN_stats(HANDLE hFile, UCHAR subnet);
void            show_IWAN_stats(HANDLE hFile, UCHAR subnet);

void            reset_IL3_stats(HANDLE hFile, UCHAR Snid);
void            show_IL3_stats(HANDLE hFile, UCHAR Snid);

CHAR            DeviceName[32];
ULONG           channels[NO_SNID_CHANNELS];
int             chanIndx;


//
// Helper functions
//
int             StrToWStr(LPWSTR wszDest, LPSTR szSrc, LONG count);
USHORT          WstrLength(IN PWSTR Wstr);

static void     help_message(void);
static char    *prog = NULL;

void _cdecl 
main(int argc, char *argv[])
{
	HANDLE          hFile = NULL;
	char          **device = NULL;

	int             c;

	ULONG           Proto = 0;
	ULONG           resetFlag = FALSE, globalFlag = FALSE;

	UCHAR           Snid = '?';

	for (chanIndx = 0; chanIndx < NO_SNID_CHANNELS; chanIndx++)
		channels[chanIndx] = chanIndx + 1;
	chanIndx = 0;

	prog = argv[0];
	if (argc == 1) {
		help_message();
		return;
	}
	while ((c = getopt(argc, argv, VALID_OPTIONS)) != -1) {
		switch (c) {
		case 'i':
			Proto |= IL3_PROTO;
			break;

		case 'l':
			Proto |= LAPD_PROTO;
			break;

		case 'w':
			Proto |= IWAN_PROTO;
			break;

		case 'z':
			resetFlag = TRUE;
			break;

		case 'g':
			globalFlag = TRUE;
			break;

		case 'c':
			channels[chanIndx++] = atol(optarg);
			break;

		}
	}
	chanIndx = (chanIndx) ? chanIndx : NO_SNID_CHANNELS;


	//
	// Open the device name
	//

	device = &argv[optind];
	strcpy(DeviceName, device[0]);
	Snid = toupper(DeviceName[strlen(DeviceName) - 1]);

#ifdef DEBUG
	printf("\nUsing Snid = '%c' (0x%hx)\n", Snid, Snid);
	printf("Attempting to open %s\n", DeviceName);
#endif

	if ((hFile = CreateFile(DeviceName,
				GENERIC_READ | GENERIC_WRITE,
				FILE_SHARE_READ | FILE_SHARE_WRITE,
				NULL,
				CREATE_ALWAYS,
				FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
				NULL)) == INVALID_HANDLE_VALUE) {
		printf("Couldn't open %s\n", DeviceName);
		return;
	} else {

#ifdef DEBUG
		printf("Successfully opened <%s> - 0x%x\n\n", DeviceName, hFile);
#endif

	}


	if (resetFlag) {

		if (Proto & LAPD_PROTO) {
			reset_LAPD_stats(hFile, Snid, globalFlag);
		}
		if (Proto & IWAN_PROTO) {
			reset_IWAN_stats(hFile, Snid);
		}
		if (Proto & IL3_PROTO) {
			reset_IL3_stats(hFile, Snid);
		}
	} else {

		if (Proto & LAPD_PROTO) {
			show_LAPD_stats(hFile, Snid, globalFlag);
		}
		if (Proto & IWAN_PROTO) {
			show_IWAN_stats(hFile, Snid);
		}
		if (Proto & IL3_PROTO) {
			show_IL3_stats(hFile, Snid);
		}
	}

	if (hFile)
		CloseHandle(hFile);

}				// end main



/**************************************/
void 
help_message()
/**************************************/
{
	fprintf(stderr, "\nUsage: %s -lapd -il3 -wan [-?] [-z] [-c<channel>]* \\\\.\\<device>\n\n", prog);
}

/**************************************/
void 
reset_IWAN_stats(HANDLE hFile, UCHAR subnet)
/**************************************/
{
	ULONG           VCWanDevice;
	ULONG           dwBytesWritten;
	BOOL            bSuccess;

	struct strioctl StrIoctl;
	SXB_S_IOCTL     SIoctl;
	wan_stioc_t     wan_s;

	WCHAR           IWANName[32];
	char            iwan[] = "/dev/iwan";

	int             chan;


	//
	// Open the IWAN layer
	//
	StrToWStr(&IWANName[0],
		  iwan,
		  strlen(iwan) + 1);


	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_OPEN,
				   (LPVOID) IWANName,
				   (ULONG) (WstrLength((PWSTR) IWANName) +
					    sizeof(WCHAR)),
				   &VCWanDevice,
				   sizeof(VCWanDevice),
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_OPEN on IWAN (ZEROSTATS) failed, GetLastError = 0x%x\n",
		       GetLastError());
		return;
	}
	//
	// O.K. Send down the WAN_ZEROSTATS command(s)
	//

	for (chan = 0; chan < chanIndx; chan++) {
		memset((char *) (&wan_s), 0, sizeof(wan_stioc_t));
		wan_s.w_type = WAN_STATS;
		wan_s.w_snid = subnet;
		wan_s.w_chanid = channels[chan];

		StrIoctl.ic_cmd = W_ZEROSTATS;
		StrIoctl.ic_timout = 0;
		StrIoctl.ic_len = sizeof(wan_stioc_t);
		StrIoctl.ic_dp = (char *) &wan_s;

		SIoctl.VCObject = (PUCHAR) VCWanDevice;
		SIoctl.Flags = I_STR;
		SIoctl.Data = (PUCHAR) & StrIoctl;

		bSuccess = DeviceIoControl(hFile,
					   (ULONG) IOCTL_S_IOCTL,
					   (LPVOID) & SIoctl,
					   sizeof(SXB_S_IOCTL),
					   NULL,
					   0,
					   &dwBytesWritten,
					   NULL);

		if (!bSuccess) {
			//
			// There was some sort of problem opening the device!
			//
			printf("S_IOCTL for W_ZEROSTATS failed, GetLastError = 0x%x\n",
			       GetLastError());
		} else {
			printf("Successfully reset IWAN(0x%x) - Subnet: %c Channel: %d statistics\n", SIoctl.ReturnCode, subnet, channels[chan]);
		}
	}

	//
	// Make sure the device is alway closed!
	//
	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_CLOSE,
				   (LPVOID) & VCWanDevice,
				   (ULONG) sizeof(VCWanDevice),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);
}



/**************************************/
void 
reset_LAPD_stats(HANDLE hFile, UCHAR subnet, int global)
/**************************************/
{

	ULONG           VCWanDevice;
	ULONG           dwBytesWritten;
	BOOL            bSuccess;

	struct strioctl StrIoctl;
	SXB_S_IOCTL     SIoctl;
	lapd_stioc_t    lapd_s;
	lapd_gstioc_t   lapd_g;

	WCHAR           LapdName[32];
	char            lapd[] = "/dev/lapd";


	//
	// Open the LAPD layer
	//
	StrToWStr(&LapdName[0],
		  lapd,
		  strlen(lapd) + 1);


	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_OPEN,
				   (LPVOID) LapdName,
				   (ULONG) (WstrLength((PWSTR) LapdName) +
					    sizeof(WCHAR)),
				   &VCWanDevice,
				   sizeof(VCWanDevice),
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_OPEN on LAPD (ZEROSTATS) failed, GetLastError = 0x%x\n",
		       GetLastError());
		return;
	}
	//
	// O.K. Send down the LAPD_ZEROSTATS command(s)
	//
	memset((char *) (&lapd_s), 0, sizeof(lapd_stioc_t));
	lapd_s.l_type = LAPD_STATS;
	lapd_s.l_snid = subnet;

	StrIoctl.ic_cmd = LAPD_ZEROSTATS;
	StrIoctl.ic_timout = 0;
	StrIoctl.ic_len = sizeof(lapd_stioc_t);
	StrIoctl.ic_dp = (char *) &lapd_s;

	SIoctl.VCObject = (PUCHAR) VCWanDevice;
	SIoctl.Flags = I_STR;
	SIoctl.Data = (PUCHAR) & StrIoctl;

	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_IOCTL,
				   (LPVOID) & SIoctl,
				   sizeof(SXB_S_IOCTL),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_IOCTL for LAPD_ZEROSTATS (Subnet) failed, GetLastError = 0x%x\n",
		       GetLastError());
	} else {
		printf("Successfully reset LAPD(0x%x) - Subnet: %c statistics\n", SIoctl.ReturnCode, subnet);
	}

	if (global) {
		memset((char *) (&lapd_g), 0, sizeof(lapd_gstioc_t));
		lapd_g.l_type = LAPD_GSTATS;

		StrIoctl.ic_cmd = LAPD_ZEROGSTATS;
		StrIoctl.ic_timout = 0;
		StrIoctl.ic_len = sizeof(lapd_gstioc_t);
		StrIoctl.ic_dp = (char *) &lapd_g;

		SIoctl.VCObject = (PUCHAR) VCWanDevice;
		SIoctl.Flags = I_STR;
		SIoctl.Data = (PUCHAR) & StrIoctl;

		bSuccess = DeviceIoControl(hFile,
					   (ULONG) IOCTL_S_IOCTL,
					   (LPVOID) & SIoctl,
					   sizeof(SXB_S_IOCTL),
					   NULL,
					   0,
					   &dwBytesWritten,
					   NULL);

		if (!bSuccess) {
			//
			// There was some sort of problem opening the device!
			//
			printf("S_IOCTL for LAPD_ZEROSTATS (Global) failed, GetLastError = 0x%x\n",
			       GetLastError());
		} else {
			printf("Successfully reset LAPD(0x%x) - Global statistics\n", SIoctl.ReturnCode);
		}
	}
	//
	// Make sure the device is alway closed!
	//
	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_CLOSE,
				   (LPVOID) & VCWanDevice,
				   (ULONG) sizeof(VCWanDevice),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);
}



/**************************************/
void 
reset_IL3_stats(HANDLE hFile, UCHAR Snid)
/**************************************/
{
	ULONG           VCWanDevice;
	ULONG           dwBytesWritten;
	BOOL            bSuccess;
	SXB_S_PUTGETMSG PutMsg;

	WCHAR           ISDNName[32];
	char            ISDN[] = "/dev/isdn";

    ULONG			tempSnid;

	il3stats_t	zero_stats;
	int ret;

	//
	// Open the ISDN layer
	//
	StrToWStr(&ISDNName[0],
		  ISDN,
		  strlen(ISDN) + 1);


	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_OPEN,
				   (LPVOID) ISDNName,
				   (ULONG) (WstrLength((PWSTR) ISDNName) +
					    sizeof(WCHAR)),
				   &VCWanDevice,
				   sizeof(VCWanDevice),
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_OPEN on ISDN (ZEROSTATS) failed, GetLastError = 0x%x\n",
		       GetLastError());
		return;
	}
	//
	// O.K. Send down the ISDN_ZEROSTATS command(s)
	//
	/*
	 * LMI interface.
	 */
	memset( (char *) &zero_stats, 0, sizeof( il3stats_t) );

    tempSnid = Snid;
	ret = il3_set( hFile, VCWanDevice, IL3_STATS, &tempSnid, sizeof(tempSnid), &zero_stats, sizeof(zero_stats) );

    if ( ret ) {
    	//
    	// There was some sort of problem opening the device!
    	//
    	printf("il3_set for IL3_STATS  failed\n" );
    } else {
    	printf("Successfully reset IL3(0x%x) statistics\n", ret);
    }

	//
	// Make sure the device is alway closed!
	//
	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_CLOSE,
				   (LPVOID) & VCWanDevice,
				   (ULONG) sizeof(VCWanDevice),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);
}



/**************************************/
void 
show_LAPD_stats(HANDLE hFile, UCHAR subnet, int global)
/**************************************/
{
	ULONG           VCWanDevice;
	ULONG           dwBytesWritten;
	BOOL            bSuccess;

	struct strioctl StrIoctl;
	SXB_S_IOCTL     SIoctl;
	lapd_stioc_t    lapd_s;
	lapd_gstioc_t   lapd_g;

	WCHAR           LapdName[32];
	char            lapd[] = "/dev/lapd";


	//
	// Open the LAPD layer
	//
	StrToWStr(&LapdName[0],
		  lapd,
		  strlen(lapd) + 1);


	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_OPEN,
				   (LPVOID) LapdName,
				   (ULONG) (WstrLength((PWSTR) LapdName) +
					    sizeof(WCHAR)),
				   &VCWanDevice,
				   sizeof(VCWanDevice),
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_OPEN on LAPD (GETSTATS) failed, GetLastError = 0x%x\n",
		       GetLastError());
		return;
	}
	if (global) {
		memset((char *) (&lapd_g), 0, sizeof(lapd_gstioc_t));
		lapd_g.l_type = LAPD_GSTATS;

		StrIoctl.ic_cmd = LAPD_GETGSTATS;
		StrIoctl.ic_timout = 0;
		StrIoctl.ic_len = sizeof(lapd_gstioc_t);
		StrIoctl.ic_dp = (char *) &lapd_g;

		SIoctl.VCObject = (PUCHAR) VCWanDevice;
		SIoctl.Flags = I_STR;
		SIoctl.Data = (PUCHAR) & StrIoctl;

		bSuccess = DeviceIoControl(hFile,
					   (ULONG) IOCTL_S_IOCTL,
					   (LPVOID) & SIoctl,
					   sizeof(SXB_S_IOCTL),
					   NULL,
					   0,
					   &dwBytesWritten,
					   NULL);

		if (!bSuccess) {
			//
			// There was some sort of problem opening the device!
			//
			printf("S_IOCTL for LAPD_GETGSTATS (Global) failed, GetLastError = 0x%x\n",
			       GetLastError());
		}
		printf("LAPD - Global statistics(0x%x)\n", SIoctl.ReturnCode);
		printf("    frames_tx: %d    frames_rx: %d\n", lapd_g.l_gstats.frames_tx, lapd_g.l_gstats.frames_rx);
		printf("    bytes_tx:  %d    bytes_rx:  %d\n\n", lapd_g.l_gstats.bytes_tx, lapd_g.l_gstats.bytes_rx);
	}
	//
	// O.K. Read the LAPD_STATS command(s)
	//
	memset((char *) (&lapd_s), 0, sizeof(lapd_stioc_t));

	lapd_s.l_type = LAPD_STATS;
	lapd_s.l_snid = subnet;

	StrIoctl.ic_cmd = LAPD_GETSTATS;
	StrIoctl.ic_timout = 0;
	StrIoctl.ic_len = sizeof(lapd_stioc_t);
	StrIoctl.ic_dp = (char *) &lapd_s;

	SIoctl.VCObject = (PUCHAR) VCWanDevice;
	SIoctl.Flags = I_STR;
	SIoctl.Data = (PUCHAR) & StrIoctl;

	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_IOCTL,
				   (LPVOID) & SIoctl,
				   sizeof(SXB_S_IOCTL),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_IOCTL for LAPD_GETSTATS (Subnet) failed, GetLastError = 0x%x\n",
		       GetLastError());
	}
	printf("LAPD - Subnet: %c statistics(0x%x)\n", subnet, SIoctl.ReturnCode);
	printf("    State:           %d(0x%x)\n\n", lapd_s.l_state, lapd_s.l_state);

	printf("    RR_rx_cmd:    %5d  RR_rx_rsp:     %5d\n"
	  "    RR_tx_cmd:    %5d  RR_tx_rsp:     %5d  RR_tx_cmd_p:  %5d\n\n"

	       "    RNR_rx_cmd:   %5d  RNR_rx_rsp:    %5d\n"
	  "    RNR_tx_cmd:   %5d  RNR_tx_rsp:    %5d  RNR_tx_cmd_p: %5d\n\n"

	       "    REJ_rx_cmd:   %5d  REJ_rx_rsp:    %5d\n"
	  "    REJ_tx_cmd:   %5d  REJ_tx_rsp:    %5d  REJ_tx_cmd_p: %5d\n\n"

	       "    I_tx_cmd:     %5d  I_rx_cmd:      %5d\n\n"

	       "    SABME_rx_cmd: %5d  SABME_tx_cmd:  %5d\n"
	       "    DISC_rx_cmd:  %5d  DISC_tx_cmd:   %5d\n"
	       "    UA_rx_rsp:    %5d  UA_tx_rsp:     %5d\n"
	       "    DM_rx_rsp:    %5d  DM_tx_rsp:     %5d\n"
	       "    UI_rx_cmd:    %5d  UI_tx_cmd:     %5d\n"
	       "    FRMR_rx_rsp:  %5d  FRMR_tx_rsp:   %5d\n\n"

	       "    XID_rx_cmd:   %5d  XID_rx_rsp:    %5d\n"
	       "    XID_tx_cmd:   %5d  XID_tx_rsp:    %5d\n\n"

	       "    rx_badlen:    %5d  rx_unknown:    %5d\n"
	  "    rx_bad:       %5d  rx_dud:        %5d  rx_ign:       %5d\n\n"

	       "    tx_rtr:       %5d  tx_ign:        %5d\n\n"

	       "    T200_exp:     %5d  T200_N200_exp: %5d\n\n"

	       "    rx_mgmt_dud:  %5d  rx_mgmt_badln: %5d\n"
	       "    rx_mgmt_ign:  %5d  rx_mgmt_unkn:  %5d\n\n"

	       "    rx_tei_assgn: %5d  rx_tei_denied: %5d\n"
	       "    rx_tei_check: %5d  rx_tei_rmv:    %5d\n\n",
	       lapd_s.l_stats.RR_rx_cmd, lapd_s.l_stats.RR_rx_cmd,
	       lapd_s.l_stats.RR_rx_rsp, lapd_s.l_stats.RR_rx_rsp,
	       lapd_s.l_stats.RR_tx_cmd, lapd_s.l_stats.RR_tx_cmd,
	       lapd_s.l_stats.RR_tx_rsp, lapd_s.l_stats.RR_tx_rsp,
	       lapd_s.l_stats.RR_tx_cmd_p, lapd_s.l_stats.RR_tx_cmd_p,
	       lapd_s.l_stats.RNR_rx_cmd, lapd_s.l_stats.RNR_rx_cmd,
	       lapd_s.l_stats.RNR_rx_rsp, lapd_s.l_stats.RNR_rx_rsp,
	       lapd_s.l_stats.RNR_tx_cmd, lapd_s.l_stats.RNR_tx_cmd,
	       lapd_s.l_stats.RNR_tx_rsp, lapd_s.l_stats.RNR_tx_rsp,
	       lapd_s.l_stats.RNR_tx_cmd_p, lapd_s.l_stats.RNR_tx_cmd_p,
	       lapd_s.l_stats.REJ_rx_cmd, lapd_s.l_stats.REJ_rx_cmd,
	       lapd_s.l_stats.REJ_rx_rsp, lapd_s.l_stats.REJ_rx_rsp,
	       lapd_s.l_stats.REJ_tx_cmd, lapd_s.l_stats.REJ_tx_cmd,
	       lapd_s.l_stats.REJ_tx_rsp, lapd_s.l_stats.REJ_tx_rsp,
	       lapd_s.l_stats.REJ_tx_cmd_p, lapd_s.l_stats.REJ_tx_cmd_p,
	       lapd_s.l_stats.I_tx_cmd, lapd_s.l_stats.I_tx_cmd,
	       lapd_s.l_stats.I_rx_cmd, lapd_s.l_stats.I_rx_cmd,
	       lapd_s.l_stats.SABME_rx_cmd, lapd_s.l_stats.SABME_rx_cmd,
	       lapd_s.l_stats.SABME_tx_cmd, lapd_s.l_stats.SABME_tx_cmd,
	       lapd_s.l_stats.DISC_rx_cmd, lapd_s.l_stats.DISC_rx_cmd,
	       lapd_s.l_stats.DISC_tx_cmd, lapd_s.l_stats.DISC_tx_cmd,
	       lapd_s.l_stats.UA_rx_rsp, lapd_s.l_stats.UA_rx_rsp,
	       lapd_s.l_stats.UA_tx_rsp, lapd_s.l_stats.UA_tx_rsp,
	       lapd_s.l_stats.DM_rx_rsp, lapd_s.l_stats.DM_rx_rsp,
	       lapd_s.l_stats.DM_tx_rsp, lapd_s.l_stats.DM_tx_rsp,
	       lapd_s.l_stats.UI_rx_cmd, lapd_s.l_stats.UI_rx_cmd,
	       lapd_s.l_stats.UI_tx_cmd, lapd_s.l_stats.UI_tx_cmd,
	       lapd_s.l_stats.FRMR_rx_rsp, lapd_s.l_stats.FRMR_rx_rsp,
	       lapd_s.l_stats.FRMR_tx_rsp, lapd_s.l_stats.FRMR_tx_rsp,
	       lapd_s.l_stats.XID_rx_cmd, lapd_s.l_stats.XID_rx_cmd,
	       lapd_s.l_stats.XID_rx_rsp, lapd_s.l_stats.XID_rx_rsp,
	       lapd_s.l_stats.XID_tx_cmd, lapd_s.l_stats.XID_tx_cmd,
	       lapd_s.l_stats.XID_tx_rsp, lapd_s.l_stats.XID_tx_rsp,
	       lapd_s.l_stats.rx_badlen, lapd_s.l_stats.rx_badlen,
	       lapd_s.l_stats.rx_unknown, lapd_s.l_stats.rx_unknown,
	       lapd_s.l_stats.rx_bad, lapd_s.l_stats.rx_bad,
	       lapd_s.l_stats.rx_dud, lapd_s.l_stats.rx_dud,
	       lapd_s.l_stats.rx_ign, lapd_s.l_stats.rx_ign,
	       lapd_s.l_stats.tx_rtr, lapd_s.l_stats.tx_rtr,
	       lapd_s.l_stats.tx_ign, lapd_s.l_stats.tx_ign,
	       lapd_s.l_stats.T200_exp, lapd_s.l_stats.T200_exp,
	       lapd_s.l_stats.T200_N200_exp, lapd_s.l_stats.T200_N200_exp,
	       lapd_s.l_stats.rx_mgmt_dud, lapd_s.l_stats.rx_mgmt_dud,
	       lapd_s.l_stats.rx_mgmt_badlen, lapd_s.l_stats.rx_mgmt_badlen,
	       lapd_s.l_stats.rx_mgmt_ign, lapd_s.l_stats.rx_mgmt_ign,
	     lapd_s.l_stats.rx_mgmt_unknown, lapd_s.l_stats.rx_mgmt_unknown,
	     lapd_s.l_stats.rx_tei_assigned, lapd_s.l_stats.rx_tei_assigned,
	       lapd_s.l_stats.rx_tei_denied, lapd_s.l_stats.rx_tei_denied,
	       lapd_s.l_stats.rx_tei_check, lapd_s.l_stats.rx_tei_check,
	       lapd_s.l_stats.rx_tei_remove, lapd_s.l_stats.rx_tei_remove);
	//
	// Make sure the device is alway closed!
	//
	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_CLOSE,
				   (LPVOID) & VCWanDevice,
				   (ULONG) sizeof(VCWanDevice),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);
}



/**************************************/
void 
show_IWAN_stats(HANDLE hFile, UCHAR subnet)
/**************************************/
{
	ULONG           VCWanDevice;
	ULONG           dwBytesWritten;
	BOOL            bSuccess;

	struct strioctl StrIoctl;
	SXB_S_IOCTL     SIoctl;
	wan_saioc_t    *wan_a;
	wan_stioc_t    *wan_t;
	isdnstatus_t   *StatusData;
	iwan_channel_stats_t *StatsData;
	char           *isdnStatus, *isdnStats;

	WCHAR           IWANName[32];
	char            iwan[] = "/dev/iwan";

	int             chan, StatusSize, StatsSize;


	//
	// Open the IWAN layer
	//

	StrToWStr(&IWANName[0],
		  iwan,
		  strlen(iwan) + 1);


	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_OPEN,
				   (LPVOID) IWANName,
				   (ULONG) (WstrLength((PWSTR) IWANName) +
					    sizeof(WCHAR)),
				   &VCWanDevice,
				   sizeof(VCWanDevice),
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_OPEN on IWAN (GETSTATS) failed, GetLastError = 0x%x\n",
		       GetLastError());
		return;
	}
	//
	// O.K. READ the WAN_GETSTATS for each requested channel
	//


	StatusSize = sizeof(wan_saioc_t) + sizeof(isdnstatus_t);
	isdnStatus = (char *) malloc((unsigned int) StatusSize);

	StatsSize = sizeof(wan_stioc_t) + sizeof(iwan_channel_stats_t);
	isdnStats = (char *) malloc((unsigned int) StatsSize);

	for (chan = 0; chan < chanIndx; chan++) {
		memset((char *) isdnStatus, 0, StatusSize);

		wan_a = (wan_saioc_t *) isdnStatus;
		wan_a->w_type = WAN_STATUS;
		wan_a->w_snid = subnet;
		wan_a->w_chanid = channels[chan];
		wan_a->w_status_offset = sizeof(wan_saioc_t);

		StrIoctl.ic_cmd = W_GETSTATUS;
		StrIoctl.ic_timout = 0;
		StrIoctl.ic_len = StatusSize;
		StrIoctl.ic_dp = (char *) wan_a;

		SIoctl.VCObject = (PUCHAR) VCWanDevice;
		SIoctl.Flags = I_STR;
		SIoctl.Data = (PUCHAR) & StrIoctl;

		bSuccess = DeviceIoControl(hFile,
					   (ULONG) IOCTL_S_IOCTL,
					   (LPVOID) & SIoctl,
					   sizeof(SXB_S_IOCTL),
					   NULL,
					   0,
					   &dwBytesWritten,
					   NULL);

		if (!bSuccess) {
			//
			// There was some sort of problem opening the device!
			//
			printf("S_IOCTL for W_GETSTATUS failed, GetLastError = 0x%x\n",
			       GetLastError());
		} else {

			StatusData = (isdnstatus_t *) ((PUCHAR) wan_a + sizeof(wan_saioc_t));
			printf("IWAN - Subnet: %c Channel: %d status(0x%x)\n", subnet, channels[chan], SIoctl.ReturnCode);
			printf("    i_powerstatus: %d(0x%x)\n"
			       "    i_actstate:    %d(0x%x)\n"
			       "    i_rxinfo:      %d(0x%x)\n"
			       "    i_txinfo:      %d(0x%x)\n\n",
			       (USHORT) StatusData->i_powerstatus, (USHORT) StatusData->i_powerstatus,
			       (USHORT) StatusData->i_actstate, (USHORT) StatusData->i_actstate,
			       (USHORT) StatusData->i_rxinfo, (USHORT) StatusData->i_rxinfo,
			       (USHORT) StatusData->i_txinfo, (USHORT) StatusData->i_txinfo);
		}

		memset((char *) isdnStats, 0, StatsSize);

		wan_t = (wan_stioc_t *) isdnStats;
		wan_t->w_type = WAN_STATS;
		wan_t->w_snid = subnet;
		wan_t->w_chanid = channels[chan];
		wan_t->w_stats_offset = sizeof(wan_stioc_t);

		StrIoctl.ic_cmd = W_GETSTATS;
		StrIoctl.ic_timout = 0;
		StrIoctl.ic_len = StatsSize;
		StrIoctl.ic_dp = (char *) wan_t;

		SIoctl.VCObject = (PUCHAR) VCWanDevice;
		SIoctl.Flags = I_STR;
		SIoctl.Data = (PUCHAR) & StrIoctl;

		bSuccess = DeviceIoControl(hFile,
					   (ULONG) IOCTL_S_IOCTL,
					   (LPVOID) & SIoctl,
					   sizeof(SXB_S_IOCTL),
					   NULL,
					   0,
					   &dwBytesWritten,
					   NULL);

		if (!bSuccess) {
			//
			// There was some sort of problem opening the device!
			//
			printf("S_IOCTL for W_GETSTATS failed, GetLastError = 0x%x\n",
			       GetLastError());
		} else {

			StatsData = (iwan_channel_stats_t *) ((PUCHAR) wan_t + sizeof(wan_stioc_t));
			printf("IWAN - Subnet: %c Channel: %d statistics(0x%x)\n", subnet, channels[chan], SIoctl.ReturnCode);
			printf("    sf_err:         %5d  loss_err:  %5d  crc_err:        %5d\n"
			       "    nob_err:        %5d  lfd_err:   %5d  ra_err:         %5d\n"
			       "    rof_err:        %5d\n\n"

			       "    no_inn_space:   %5d  no_wan_mp: %5d  no_fe_and_no_c: %5d\n\n"

			       "    tx_size_err:    %5d  rx_sz_err: %5d\n"
			       "    tx_prep:        %5d  tx_good:   %5d  rx_good:        %5d\n\n"

			       "    t_hi:           %5d  t_fi:      %5d  t_ifc:          %5d\n"
			       "    t_sf:           %5d  t_err:     %5d  t_fo:           %5d\n\n"

			       "    r_hi:           %5d  r_fi:      %5d  r_ifc:          %5d\n"
			       "    r_sf:           %5d  r_err:     %5d  r_fo:           %5d\n\n",
			       StatsData->sf_err,
			       StatsData->loss_err,
			       StatsData->crc_err,
			       StatsData->nob_err,
			       StatsData->lfd_err,
			       StatsData->ra_err,
			       StatsData->rof_err,
			       StatsData->no_inn_space,
			       StatsData->no_wan_mp,
			       StatsData->no_fe_and_no_c,
			       StatsData->tx_size_err,
			       StatsData->rx_size_err,
			       StatsData->tx_prep,
			       StatsData->tx_good,
			       StatsData->rx_good,
			       StatsData->t_hi,
			       StatsData->t_fi,
			       StatsData->t_ifc,
			       StatsData->t_sf,
			       StatsData->t_err,
			       StatsData->t_fo,
			       StatsData->r_hi,
			       StatsData->r_fi,
			       StatsData->r_ifc,
			       StatsData->r_sf,
			       StatsData->r_err,
			       StatsData->r_fo);
		}
	}
	if (isdnStatus)
		free(isdnStatus);

	if (isdnStats)
		free(isdnStats);

	//
	// Make sure the device is alway closed!
	//
	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_CLOSE,
				   (LPVOID) & VCWanDevice,
				   (ULONG) sizeof(VCWanDevice),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);
}



/**************************************/
void 
show_IL3_stats(HANDLE hFile, UCHAR Snid)
/**************************************/
{
	ULONG           VCWanDevice;
	ULONG           dwBytesWritten;
	BOOL            bSuccess;
	SXB_S_PUTGETMSG PutMsg;

	WCHAR           ISDNName[32];
	char            ISDN[] = "/dev/isdn";
	ULONG			tempSnid;

	il3stats_t	get_stats;
	int		ret;

	//
	// Open the ISDN layer
	//
	StrToWStr(&ISDNName[0],
		  ISDN,
		  strlen(ISDN) + 1);


	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_OPEN,
				   (LPVOID) ISDNName,
				   (ULONG) (WstrLength((PWSTR) ISDNName) +
					    sizeof(WCHAR)),
				   &VCWanDevice,
				   sizeof(VCWanDevice),
				   &dwBytesWritten,
				   NULL);

	if (!bSuccess) {
		//
		// There was some sort of problem opening the device!
		//
		printf("S_OPEN on ISDN (ZEROSTATS) failed, GetLastError = 0x%x\n",
		       GetLastError());
		return;
	}

	//
	// OK read and display the IL3 Stats
	//
	memset( (char *) &get_stats, 0, sizeof( il3stats_t) ); 

    tempSnid = Snid;
	ret = il3_get( hFile, VCWanDevice, IL3_STATS, &tempSnid, sizeof(tempSnid), (int*)&get_stats, sizeof(get_stats) ); 

    if( ret ) {
	   printf( "il3_get for stats failed(0x%x)\n", ret );
	} else {
	   printf( "IL3 - statistics\n" );
	   printf( "   no_out_calls:     %5d\n"
	           "   no_out_calls_acc: %5d\n"
	           "   no_out_calls_rej: %5d\n\n"

               "   no_in_calls:      %5d\n"
               "   no_in_calls_up:   %5d\n"
               "   no_in_calls_acc:  %5d\n"
               "   no_in_calls_rej:  %5d\n\n"

               "   no_unk_msg_in:    %5d\n"
               "   no_bad_msg_in:    %5d\n",
               (int)get_stats.no_out_calls,
               (int)get_stats.no_out_calls_acc,
               (int)get_stats.no_out_calls_rej,
               (int)get_stats.no_in_calls,
               (int)get_stats.no_in_calls_up,
               (int)get_stats.no_in_calls_acc,
               (int)get_stats.no_in_calls_rej,
               (int)get_stats.no_unk_msg_in,
               (int)get_stats.no_bad_msg_in );
	}

	//
	// Make sure the device is alway closed!
	//
	bSuccess = DeviceIoControl(hFile,
				   (ULONG) IOCTL_S_CLOSE,
				   (LPVOID) & VCWanDevice,
				   (ULONG) sizeof(VCWanDevice),
				   NULL,
				   0,
				   &dwBytesWritten,
				   NULL);
}



/**************************************/
int 
StrToWStr(LPWSTR wszDest, LPSTR szSrc, LONG count)
/**************************************/
{
	LONG            i;

	for (i = 0; i < count; i++) {
		wszDest[i] = szSrc[i];
	}

	return (i - 1);
}



USHORT WstrLength(IN PWSTR Wstr)
/*
 * ++
 * 
 * Routine Description:
 * 
 * Determines the number of bytes used by the passed in Wstr
 * 
 * Arguments:
 * 
 * Wstr - Pointer to wide character string.
 * 
 * Return Value:
 * 
 * Length, in bytes.
 * 
 * -- */
{
	USHORT          Length = 0;

	while (*Wstr++) {
		Length += sizeof(WCHAR);
	}
	return (Length);
}				// end DigiWstrLength
