|
|
//****************************************************************************
//
// Microsoft NT Remote Access Service
//
// Copyright (C) 1992-93 Microsft Corporation. All rights reserved.
//
// Filename: serial.c
//
// Revision History
//
// Sep 3, 1992 J. Perry Hannah Created
//
//
// Description: This file contains all entry points for SERIAL.DLL
// which is the media DLL for serial ports.
//
//****************************************************************************
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <rasman.h>
#include <raserror.h>
#include <rasfile.h>
#include <mprlog.h>
#include <rtutils.h>
#include <rasmxs.h>
#include <wanpub.h>
#include <asyncpub.h>
#include <media.h>
#include <serial.h>
#include <serialpr.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
//* Global Variables *******************************************************
//
SERIALPCB *gpSerialPCB; // Points to Serial PCB linked list
HANDLE ghRasfileMutex; // Mutex used to protect access to Rasfile
HRASFILE ghIniFile; // Handle to Serial.ini memory image
HANDLE ghAsyMac; // Handle to AsyncMac driver
DWORD gLastError;
//* Prototypes For APIs That Are Called Internally *************************
//
DWORD PortClearStatistics(HANDLE hIOPort);
OVERLAPPED overlapped ;
//* Initialization Routine *************************************************
//
//* SerialDllEntryPoint
//
// Function: Initializes Serial DLL when the DLL is loaded into memory,
// and cleans up when the last process detaches from the DLL.
//
// Returns: TRUE if successful, else FALSE.
//
//*
BOOL APIENTRY SerialDllEntryPoint(HANDLE hDll, DWORD dwReason, LPVOID pReserved) { static BOOL bFirstCall = TRUE;
char szIniFilePath[MAX_PATH]; WCHAR szDriverName[] = ASYNCMAC_FILENAME;
DebugPrintf(("SerialDllEntryPoint\n")); //DbgPrint("SerialDllEntryPoint\n");
switch(dwReason) { case DLL_PROCESS_ATTACH:
if (bFirstCall) { DebugPrintf(("\tProcess Attach.\n"));
// Open Serial.ini file
*szIniFilePath = '\0'; GetIniFileName(szIniFilePath, sizeof(szIniFilePath)); ghIniFile = RasfileLoad(szIniFilePath, RFM_READONLY, NULL, NULL);
DebugPrintf(("INI: %s, ghIniFile: 0x%08x\n", szIniFilePath, ghIniFile));
/*
if (ghIniFile == INVALID_HRASFILE) { LogError(ROUTERLOG_CANNOT_OPEN_SERIAL_INI, 0, NULL, 0xffffffff); return(FALSE); } */
if ((ghRasfileMutex = CreateMutex (NULL,FALSE,NULL)) == NULL) return FALSE ;
// Get handle to Asyncmac driver
/*
ghAsyMac = CreateFileW(szDriverName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, //No security attribs
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); //No template file
DebugPrintf(("ghAsyMac: 0x%08x\n", ghAsyMac));
if (ghAsyMac == INVALID_HANDLE_VALUE) { DebugPrintf(("CreateFileError: %d\n", GetLastError()));
LogError(ROUTERLOG_CANNOT_GET_ASYNCMAC_HANDLE, 0, NULL, 0xffffffff); return(FALSE); } */
bFirstCall = FALSE; } break;
case DLL_PROCESS_DETACH: DebugPrintf(("\tProcess Detach.\n")); if(INVALID_HANDLE_VALUE != ghRasfileMutex && NULL != ghRasfileMutex) { CloseHandle(ghRasfileMutex); ghRasfileMutex = INVALID_HANDLE_VALUE; } break;
case DLL_THREAD_ATTACH: DebugPrintf(("\tThread Attach.\n")); break;
case DLL_THREAD_DETACH: DebugPrintf(("\tThread Detach.\n")); break; }
return(TRUE);
UNREFERENCED_PARAMETER(hDll); UNREFERENCED_PARAMETER(pReserved); }
//* Serial APIs ************************************************************
//
//* PortEnum ---------------------------------------------------------------
//
// Function: This API returns a buffer containing a PortMediaInfo struct.
//
// Returns: SUCCESS
// ERROR_BUFFER_TOO_SMALL
// ERROR_READING_SECTIONNAME
// ERROR_READING_DEVICETYPE
// ERROR_READING_DEVICENAME
// ERROR_READING_USAGE
// ERROR_BAD_USAGE_IN_INI_FILE
//
//*
DWORD APIENTRY PortEnum(BYTE *pBuffer, DWORD *pdwSize, DWORD *pdwNumPorts) { DWORD dwAvailable; TCHAR szUsage[RAS_MAXLINEBUFLEN]; CHAR szMacName[MAC_NAME_SIZE] ; PortMediaInfo *pPMI; BYTE buffer [1000] ; DWORD dwBytesReturned; TCHAR *pszBuffer = NULL; DWORD dwErr = ERROR_SUCCESS;
memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
DebugPrintf(("PortEnum\n"));
// Count number of sections in serial.ini
*pdwNumPorts = 0;
// Begin Exclusion
WaitForSingleObject(ghRasfileMutex, INFINITE);
if ( INVALID_HRASFILE != ghIniFile && RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_FILE)) (*pdwNumPorts)++; else { *pdwSize = 0;
// End Exclusion
ReleaseMutex(ghRasfileMutex); return(SUCCESS); }
while(RasfileFindNextLine(ghIniFile, RFL_SECTION, RFS_FILE)) (*pdwNumPorts)++;
// End Exclusion
ReleaseMutex(ghRasfileMutex);
// Calculate size of buffer needed
dwAvailable = *pdwSize; *pdwSize = sizeof(PortMediaInfo) * (*pdwNumPorts); if (*pdwSize > dwAvailable) return(ERROR_BUFFER_TOO_SMALL);
// Translate serial.ini file section by section into pBuffer
pPMI = (PortMediaInfo *) pBuffer;
// Begin Exclusion
WaitForSingleObject(ghRasfileMutex, INFINITE);
RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_FILE);
#if 0
// Need to get the MAC name
if (!DeviceIoControl(ghAsyMac, IOCTL_ASYMAC_ENUM, buffer, sizeof(buffer), buffer, sizeof(buffer), &dwBytesReturned, &overlapped)) { // End Exclusion
ReleaseMutex(ghRasfileMutex); return(GetLastError()); }
wcstombs(szMacName, ((PASYMAC_ENUM)buffer)->AdapterInfo[0].MacName, wcslen(((PASYMAC_ENUM)buffer)->AdapterInfo[0].MacName)+1) ;
#else
szMacName[0] = '\0' ; #endif
pszBuffer = LocalAlloc(LPTR, RAS_MAXLINEBUFLEN); if(NULL == pszBuffer) { ReleaseMutex(ghRasfileMutex); return GetLastError(); }
do { // Get Section Name (same as Port Name)
if (!RasfileGetSectionName(ghIniFile, pPMI->PMI_Name)) { // End Exclusion
ReleaseMutex(ghRasfileMutex); dwErr = ERROR_READING_SECTIONNAME; break; }
// Set Binding Name
strcpy (pPMI->PMI_MacBindingName, szMacName) ;
// Get Device Type
if(!(RasfileFindNextKeyLine(ghIniFile, SER_DEVICETYPE_KEY, RFS_SECTION) && RasfileGetKeyValueFields(ghIniFile, NULL, pszBuffer/* pPMI->PMI_DeviceType*/))) { // End Exclusion
CopyMemory(pPMI->PMI_DeviceType, pszBuffer, MAX_DEVICETYPE_NAME); ReleaseMutex(ghRasfileMutex); dwErr = ERROR_READING_DEVICETYPE; break; }
CopyMemory(pPMI->PMI_DeviceType, pszBuffer, MAX_DEVICETYPE_NAME); ZeroMemory(pszBuffer, sizeof(RAS_MAXLINEBUFLEN));
// Get Device Name
if (!(RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_SECTION) && RasfileFindNextKeyLine(ghIniFile, SER_DEVICENAME_KEY, RFS_SECTION) && RasfileGetKeyValueFields(ghIniFile, NULL, pszBuffer /*pPMI->PMI_DeviceName*/))) { // End Exclusion
CopyMemory(pPMI->PMI_DeviceName, pszBuffer, MAX_DEVICE_NAME); ReleaseMutex(ghRasfileMutex); dwErr = ERROR_READING_DEVICENAME; break; }
CopyMemory(pPMI->PMI_DeviceName, pszBuffer, MAX_DEVICE_NAME); ZeroMemory(pszBuffer, RAS_MAXLINEBUFLEN);
// Get Usage
if (!(RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_SECTION) && RasfileFindNextKeyLine(ghIniFile, SER_USAGE_KEY, RFS_SECTION) && RasfileGetKeyValueFields(ghIniFile, NULL, pszBuffer /*szUsage*/))) { // End Exclusion
CopyMemory(szUsage, pszBuffer, RAS_MAXLINEBUFLEN); ReleaseMutex(ghRasfileMutex); dwErr = ERROR_READING_USAGE; break; }
CopyMemory(szUsage, pszBuffer, RAS_MAXLINEBUFLEN);
if (!StrToUsage(szUsage, &(pPMI->PMI_Usage))) { // End Exclusion
ReleaseMutex(ghRasfileMutex); dwErr = ERROR_BAD_USAGE_IN_INI_FILE; break; }
pPMI->PMI_LineDeviceId = INVALID_TAPI_ID; pPMI->PMI_AddressId = INVALID_TAPI_ID;
pPMI++;
}while(RasfileFindNextLine(ghIniFile, RFL_SECTION, RFS_FILE));
if(NULL != pszBuffer) { LocalFree(pszBuffer); } // End Exclusion
ReleaseMutex(ghRasfileMutex); return(dwErr); }
//* PortOpen ---------------------------------------------------------------
//
// Function: This API opens a COM port. It takes the port name in ASCIIZ
// form and supplies a handle to the open port. hNotify is use
// to notify the caller if the device on the port shuts down.
//
// PortOpen allocates a SerialPCB and places it at the head of
// the linked list of Serial Port Control Blocks.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_CONFIGURED
// ERROR_DEVICE_NOT_READY
//
//*
DWORD APIENTRY PortOpen( char *pszPortName, HANDLE *phIOPort, HANDLE hIoCompletionPort, DWORD dwCompletionKey) { SERIALPCB *pSPCB ; DWORD dwRC, dwStatus = 0; TCHAR szPort[MAX_PATH]; WCHAR szDriverName[] = ASYNCMAC_FILENAME;
try { DebugPrintf(("PortOpen: %s\n", pszPortName));
// Check serial.ini to see that pszPortName is configured for RAS
// Begin Exclusion
if(INVALID_HRASFILE == ghIniFile) { return ERROR_PORT_NOT_CONFIGURED; }
WaitForSingleObject(ghRasfileMutex, INFINITE);
#if DBG
ASSERT(INVALID_HRASFILE != ghIniFile ); #endif
if (!RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE)) { // End Exclusion
ReleaseMutex(ghRasfileMutex); return(ERROR_PORT_NOT_CONFIGURED); } // End Exclusion
ReleaseMutex(ghRasfileMutex);
// Prepend \\.\ to COMx
strcpy(szPort, "\\\\.\\"); strcat(szPort, pszPortName);
// Open Port
*phIOPort = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, FILE_EXCLUSIVE_MODE, NULL, //No Security Attributes
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); //No Template File
DebugPrintf(("hioport: 0x%08x\n", *phIOPort)); //DbgPrint("hioport: 0x%08x\n", *phIOPort);
if (*phIOPort == INVALID_HANDLE_VALUE) { dwRC = GetLastError(); if (dwRC == ERROR_ACCESS_DENIED) return (ERROR_PORT_ALREADY_OPEN); else if (dwRC == ERROR_FILE_NOT_FOUND) return (ERROR_PORT_NOT_FOUND) ; else return(dwRC); }
//
// Associate an I/O completion port with
// the file handle.
//
if (CreateIoCompletionPort( *phIOPort, hIoCompletionPort, dwCompletionKey, 0) == NULL) { CloseHandle(*phIOPort); *phIOPort = NULL; return GetLastError(); }
#ifdef notdef
{ DWORD dwBytesReturned ;
#define FILE_DEVICE_SERIAL_PORT 0x0000001b
#define _SERIAL_CONTROL_CODE(request,method) \
((FILE_DEVICE_SERIAL_PORT)<<16 | (request<<2) | method) #define IOCTL_SERIAL_PRIVATE_RAS _SERIAL_CONTROL_CODE(4000, METHOD_BUFFERED)
DeviceIoControl(*phIOPort, IOCTL_SERIAL_PRIVATE_RAS, NULL, 0, NULL, 0, &dwBytesReturned, NULL) ; } #endif
// Set Queue sizes and default values for Comm Port
if (!SetupComm(*phIOPort, INPUT_QUEUE_SIZE, OUTPUT_QUEUE_SIZE)) { LogError(ROUTERLOG_SERIAL_QUEUE_SIZE_SMALL, 0, NULL, 0xffffffff); }
SetCommDefaults(*phIOPort, pszPortName);
// Add a Serial PCB to head of list and set eDeviceType
AddPortToList(*phIOPort, pszPortName);
pSPCB = FindPortInList(*phIOPort, NULL) ; //Find port just added
if(NULL == pSPCB) { CloseHandle(*phIOPort); *phIOPort = NULL; return ERROR_PORT_NOT_FOUND; }
// Get handle to Asyncmac driver
pSPCB->hAsyMac = CreateFileW(szDriverName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, //No security attribs
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); //No template file
DebugPrintf(("pSPCB->hAsyMac: 0x%08x\n", pSPCB->hAsyMac)); //DbgPrint("pSPCB->hAsyMac: 0x%08x\n", pSPCB->hAsyMac);
if (pSPCB->hAsyMac == INVALID_HANDLE_VALUE) { DWORD dwErr; dwErr = GetLastError(); DebugPrintf(("CreateFileError: %d\n", dwErr)); //DbgPrint("CreateFileError: %d\n", dwErr);
LogError(ROUTERLOG_CANNOT_GET_ASYNCMAC_HANDLE, 0, NULL, 0xffffffff); CloseHandle(*phIOPort); *phIOPort = NULL; return(dwErr); }
//
// Associate the I/O completion port with
// the asyncmac file handle
//
if (CreateIoCompletionPort(pSPCB->hAsyMac, hIoCompletionPort, dwCompletionKey, 0) == NULL) { DWORD dwErr; dwErr = GetLastError(); //DbgPrint("PortOpen: Failed to create IoCompletionPort %d\n", dwErr);
CloseHandle(*phIOPort); *phIOPort = NULL; return dwErr; } dwRC = InitCarrierBps(pszPortName, pSPCB->szCarrierBPS); if (dwRC != SUCCESS) { gLastError = dwRC; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); }
// Check that device is powered on and ready (DSR is up) If it is then
// we monitor DSR - else - we do not monitor DSR until we are connected.
//
GetCommModemStatus(*phIOPort, &dwStatus);
pSPCB->dwPreviousModemStatus = 0; if ( ! (dwStatus & MS_DSR_ON)) // DSR is not raised by the device = assume that it will not raise
// it until its connected.
//
pSPCB->dwActiveDSRMask = pSPCB->dwMonitorDSRMask = 0 ; else { // Tell system to signal rasman if DSR drops
pSPCB->dwActiveDSRMask = pSPCB->dwMonitorDSRMask = EV_DSR ; //DbgPrint("PortOpen: Setting mask 0x%x\n", EV_DSR);
SetCommMask(*phIOPort, EV_DSR);
if (!WaitCommEvent(*phIOPort, &(pSPCB->dwEventMask), (LPOVERLAPPED)&(pSPCB->MonitorDevice))) {
//DbgPrint("PortOpen: WaitCommEvent. %d\n", GetLastError());
}
}
// Set values in Serial Port Control Block
GetDefaultOffStr(*phIOPort, pszPortName);
} except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH) { return(gLastError); }
return(SUCCESS); }
//* PortClose --------------------------------------------------------------
//
// Function: This API closes the COM port for the input handle. It also
// finds the SerialPCB for the input handle, removes it from
// the linked list, and frees the memory for it
//
// Returns: SUCCESS
// Values returned by GetLastError()
//
//*
DWORD APIENTRY PortClose (HANDLE hIOPort) { SERIALPCB *pPrev, *pSPCB = gpSerialPCB;
DebugPrintf(("PortClose\n"));
// Find the SerialPCB which contains hIOPOrt
pSPCB = FindPortInList(hIOPort, &pPrev);
if (pSPCB == NULL) return(ERROR_PORT_NOT_OPEN);
// Remove the found SerialPCB
if (pSPCB == gpSerialPCB) gpSerialPCB = pSPCB->pNextSPCB; else pPrev->pNextSPCB = pSPCB->pNextSPCB;
// Cancel wait on this port (WaitCommEvent)
//
//DbgPrint("PortClose: Setting mask to 0\n");
SetCommMask(hIOPort, 0);
// Drop DTR
//
EscapeCommFunction(hIOPort, CLRDTR);
// Close COM Port
//
if (!CloseHandle(hIOPort)) return(GetLastError());
// close the asymac file we associated with this com port
if (!CloseHandle(pSPCB->hAsyMac)) return GetLastError();
// Free portcontrolblock: note this must be done after CloseHandle since the struct
// contains an overlapped struct used for i/o on the port. this overlapped struct
// is freed when the handle to the port is closed.
//
free(pSPCB);
return(SUCCESS); }
//* PortGetInfo ------------------------------------------------------------
//
// Function: This API returns a block of information to the caller about
// the port state. This API may be called before the port is
// open in which case it will return inital default values
// instead of actual port values.
//
// If the API is to be called before the port is open, set hIOPort
// to INVALID_HANDLE_VALUE and pszPortName to the port name. If
// hIOPort is valid (the port is open), pszPortName may be set
// to NULL.
//
// hIOPort pSPCB := FindPortNameInList() Port
// ------- ----------------------------- ------
// valid x open
// invalid non_null open
// invalid null closed
//
// Returns: SUCCESS
// ERROR_BUFFER_TOO_SMALL
//*
DWORD APIENTRY PortGetInfo(HANDLE hIOPort, TCHAR *pszPortName, BYTE *pBuffer, DWORD *pdwSize) { SERIALPCB *pSPCB; DCB DCB; RAS_PARAMS *pParam; TCHAR *pValue; TCHAR szDefaultOff[RAS_MAXLINEBUFLEN]; TCHAR szClientDefaultOff[RAS_MAXLINEBUFLEN]; TCHAR szDeviceType[MAX_DEVICETYPE_NAME + 1]; TCHAR szDeviceName[MAX_DEVICE_NAME + 1]; TCHAR szPortName[MAX_PORT_NAME + 1]; TCHAR szConnectBPS[MAX_BPS_STR_LEN], szCarrierBPS[MAX_BPS_STR_LEN]; DWORD dwConnectBPSLen, dwCarrierBPSLen, dwDefaultOffLen; DWORD dwDeviceTypeLen, dwDeviceNameLen, dwPortNameLen; DWORD dwClientDefaultOffLen; DWORD dwStructSize; DWORD dwAvailable, dwNumOfParams = 12;
try {
DebugPrintf(("PortGetInfo\n"));
if (hIOPort == INVALID_HANDLE_VALUE && (pSPCB = FindPortNameInList(pszPortName)) == NULL) { // Port is not yet open
// Read from Serial.ini
GetValueFromFile(pszPortName, SER_DEFAULTOFF_KEY, szDefaultOff, RAS_MAXLINEBUFLEN); GetValueFromFile(pszPortName, SER_MAXCONNECTBPS_KEY, szConnectBPS, MAX_BPS_STR_LEN); GetValueFromFile(pszPortName, SER_MAXCARRIERBPS_KEY, szCarrierBPS, MAX_BPS_STR_LEN); GetValueFromFile(pszPortName, SER_DEVICETYPE_KEY, szDeviceType, MAX_DEVICETYPE_NAME + 1); GetValueFromFile(pszPortName, SER_DEVICENAME_KEY, szDeviceName, MAX_DEVICE_NAME + 1); strcpy(szPortName, pszPortName);
// Set RAS default values in the DCB
SetDcbDefaults(&DCB); } else { // Port is open; Get a Device Control Block with current port values
if (hIOPort != INVALID_HANDLE_VALUE) { pSPCB = FindPortInList(hIOPort, NULL); if (pSPCB == NULL) { gLastError = ERROR_PORT_NOT_OPEN; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); } }
if (!GetCommState(pSPCB->hIOPort, &DCB)) { gLastError = GetLastError(); RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); }
_itoa(DCB.BaudRate, szConnectBPS, 10); strcpy(szCarrierBPS, pSPCB->szCarrierBPS); strcpy(szDefaultOff, pSPCB->szDefaultOff); strcpy(szDeviceType, pSPCB->szDeviceType); strcpy(szDeviceName, pSPCB->szDeviceName); strcpy(szPortName, pSPCB->szPortName); }
// Read from Serial.ini even if port is open
GetValueFromFile(szPortName, SER_C_DEFAULTOFFSTR_KEY, szClientDefaultOff, RAS_MAXLINEBUFLEN);
// Calculate Buffer size needed
dwStructSize = sizeof(RASMAN_PORTINFO) + sizeof(RAS_PARAMS) * (dwNumOfParams - 1);
dwConnectBPSLen = strlen(szConnectBPS); dwCarrierBPSLen = strlen(szCarrierBPS); dwDeviceTypeLen = strlen(szDeviceType); dwDeviceNameLen = strlen(szDeviceName); dwDefaultOffLen = strlen(szDefaultOff); dwPortNameLen = strlen(szPortName); dwClientDefaultOffLen = strlen(szClientDefaultOff);
dwAvailable = *pdwSize; *pdwSize = (dwStructSize + dwConnectBPSLen + dwCarrierBPSLen + dwDeviceTypeLen + dwDeviceNameLen + dwDefaultOffLen + dwPortNameLen + dwClientDefaultOffLen + + 7L); //Zero bytes
if (*pdwSize > dwAvailable) return(ERROR_BUFFER_TOO_SMALL);
// Fill in Buffer
((RASMAN_PORTINFO *)pBuffer)->PI_NumOfParams = ( WORD ) dwNumOfParams;
pParam = ((RASMAN_PORTINFO *)pBuffer)->PI_Params; pValue = pBuffer + dwStructSize;
strcpy(pParam->P_Key, SER_CONNECTBPS_KEY); pParam->P_Type = String; pParam->P_Attributes = 0; pParam->P_Value.String.Length = dwConnectBPSLen; pParam->P_Value.String.Data = pValue; strcpy(pParam->P_Value.String.Data, szConnectBPS); pValue += dwConnectBPSLen + 1;
pParam++; strcpy(pParam->P_Key, SER_DATABITS_KEY); pParam->P_Type = Number; pParam->P_Attributes = 0; pParam->P_Value.Number = DCB.ByteSize;
pParam++; strcpy(pParam->P_Key, SER_PARITY_KEY); pParam->P_Type = Number; pParam->P_Attributes = 0; pParam->P_Value.Number = DCB.Parity;
pParam++; strcpy(pParam->P_Key, SER_STOPBITS_KEY); pParam->P_Type = Number; pParam->P_Attributes = 0; pParam->P_Value.Number = DCB.StopBits;
pParam++; strcpy(pParam->P_Key, SER_HDWFLOWCTRLON_KEY); pParam->P_Type = Number; pParam->P_Attributes = 0; pParam->P_Value.Number = DCB.fOutxCtsFlow;
pParam++; strcpy(pParam->P_Key, SER_CARRIERBPS_KEY); pParam->P_Type = String; pParam->P_Attributes = 0; pParam->P_Value.String.Length = dwCarrierBPSLen; pParam->P_Value.String.Data = pValue; strcpy(pParam->P_Value.String.Data, szCarrierBPS); pValue += dwCarrierBPSLen + 1;
pParam++; strcpy(pParam->P_Key, SER_ERRORCONTROLON_KEY); pParam->P_Type = Number; pParam->P_Attributes = 0; if (pSPCB == NULL) pParam->P_Value.Number = FALSE; else pParam->P_Value.Number = pSPCB->bErrorControlOn;
pParam++; strcpy(pParam->P_Key, SER_DEFAULTOFFSTR_KEY); pParam->P_Type = String; pParam->P_Attributes = 0; pParam->P_Value.String.Length = dwDefaultOffLen; pParam->P_Value.String.Data = pValue; strcpy(pParam->P_Value.String.Data, szDefaultOff); pValue += dwDefaultOffLen + 1;
pParam++; strcpy(pParam->P_Key, SER_DEVICETYPE_KEY); pParam->P_Type = String; pParam->P_Attributes = 0; pParam->P_Value.String.Length = dwDeviceTypeLen; pParam->P_Value.String.Data = pValue; strcpy(pParam->P_Value.String.Data, szDeviceType); pValue += dwDeviceTypeLen + 1;
pParam++; strcpy(pParam->P_Key, SER_DEVICENAME_KEY); pParam->P_Type = String; pParam->P_Attributes = 0; pParam->P_Value.String.Length = dwDeviceNameLen; pParam->P_Value.String.Data = pValue; strcpy(pParam->P_Value.String.Data, szDeviceName); pValue += dwDeviceNameLen + 1;
pParam++; strcpy(pParam->P_Key, SER_PORTNAME_KEY); pParam->P_Type = String; pParam->P_Attributes = 0; pParam->P_Value.String.Length = dwPortNameLen; pParam->P_Value.String.Data = pValue; strcpy(pParam->P_Value.String.Data, szPortName); pValue += dwPortNameLen + 1;
pParam++; strcpy(pParam->P_Key, SER_C_DEFAULTOFFSTR_KEY); pParam->P_Type = String; pParam->P_Attributes = 0; pParam->P_Value.String.Length = dwClientDefaultOffLen; pParam->P_Value.String.Data = pValue; strcpy(pParam->P_Value.String.Data, szClientDefaultOff); //pValue += dwClientDefaultOffLen + 1;
return(SUCCESS);
} except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH) { return(gLastError); } }
//* PortSetInfo ------------------------------------------------------------
//
// Function: The values for most input keys are used to set the port
// parameters directly. However, the carrier BPS and the
// error conrol on flag set fields in the Serial Port Control
// Block only, and not the port.
//
// Returns: SUCCESS
// ERROR_WRONG_INFO_SPECIFIED
// Values returned by GetLastError()
//*
DWORD APIENTRY PortSetInfo(HANDLE hIOPort, RASMAN_PORTINFO *pInfo) { RAS_PARAMS *p; SERIALPCB *pSPCB; DCB DCB; WORD i; BOOL bTypeError = FALSE;
try {
DebugPrintf(("PortSetInfo\n\thPort = %d\n", hIOPort));
// Find the SerialPCB which contains hIOPOrt
pSPCB = FindPortInList(hIOPort, NULL);
if (pSPCB == NULL) { gLastError = ERROR_PORT_NOT_OPEN; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); }
// Get a Device Control Block with current port values
if (!GetCommState(hIOPort, &DCB)) return(GetLastError());
// Set DCB and PCB values
for (i=0, p=pInfo->PI_Params; i<pInfo->PI_NumOfParams; i++, p++) { // Set DCB values
if (_stricmp(p->P_Key, SER_CONNECTBPS_KEY) == 0)
DCB.BaudRate = ValueToNum(p);
else if (_stricmp(p->P_Key, SER_DATABITS_KEY) == 0)
DCB.ByteSize = (BYTE) ValueToNum(p);
else if (_stricmp(p->P_Key, SER_PARITY_KEY) == 0)
DCB.Parity = (BYTE) ValueToNum(p);
else if (_stricmp(p->P_Key, SER_STOPBITS_KEY) == 0)
DCB.StopBits = (BYTE) ValueToNum(p);
else if (_stricmp(p->P_Key, SER_HDWFLOWCTRLON_KEY) == 0)
DCB.fOutxCtsFlow = ValueToBool(p);
// Set PCB values
else if (_stricmp(p->P_Key, SER_CARRIERBPS_KEY) == 0)
if (p->P_Type == String) { strncpy(pSPCB->szCarrierBPS, p->P_Value.String.Data, p->P_Value.String.Length);
pSPCB->szCarrierBPS[p->P_Value.String.Length] = '\0'; } else _itoa(p->P_Value.Number, pSPCB->szCarrierBPS, 10);
else if (_stricmp(p->P_Key, SER_ERRORCONTROLON_KEY) == 0)
pSPCB->bErrorControlOn = ValueToBool(p);
else if (_stricmp(p->P_Key, SER_DEFAULTOFF_KEY) == 0)
if (p->P_Type == String) { strncpy(pSPCB->szDefaultOff, p->P_Value.String.Data, p->P_Value.String.Length);
pSPCB->szDefaultOff[p->P_Value.String.Length] = '\0'; } else pSPCB->szDefaultOff[0] = USE_DEVICE_INI_DEFAULT;
else return(ERROR_WRONG_INFO_SPECIFIED);
} // for
// Send DCB to Port
if (!SetCommState(hIOPort, &DCB)) return(GetLastError());
return(SUCCESS);
} except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH) { return(gLastError); } }
//* PortTestSignalState ----------------------------------------------------
//
// Function: This API indicates the state of the DSR and DTR lines.
// DSR - Data Set Ready
// DCD - Data Carrier Detect (RLSD - Received Line Signal Detect)
//
// Returns: SUCCESS
// Values returned by GetLastError()
//
//*
DWORD APIENTRY PortTestSignalState(HANDLE hIOPort, DWORD *pdwDeviceState) { DWORD dwModemStatus; SERIALPCB *pSPCB; DWORD dwSetMask = 0 ;
DebugPrintf(("PortTestSignalState\n"));
*pdwDeviceState = 0;
if ((pSPCB = FindPortInList (hIOPort, NULL)) == NULL) return ERROR_PORT_NOT_OPEN ;
if (!GetCommModemStatus(hIOPort, &dwModemStatus)) { *pdwDeviceState = 0xffffffff; return(GetLastError()); }
// If DSR is down AND it was up before then mark it as a hw failure.
//
if ((!(dwModemStatus & MS_DSR_ON)) && (pSPCB->dwMonitorDSRMask)) *pdwDeviceState |= SS_HARDWAREFAILURE;
// Similarly, if DCD is down and it was up before then link has dropped.
//
if (!(dwModemStatus & MS_RLSD_ON)) *pdwDeviceState |= SS_LINKDROPPED; else dwSetMask = EV_RLSD ;
if (pSPCB->uRasEndpoint != INVALID_HANDLE_VALUE) { ASYMAC_DCDCHANGE A ; DWORD dwBytesReturned;
A.MacAdapter = NULL ; A.hNdisEndpoint = (HANDLE) pSPCB->uRasEndpoint ; DeviceIoControl(pSPCB->hAsyMac, IOCTL_ASYMAC_DCDCHANGE, &A, sizeof(A), &A,sizeof(A), &dwBytesReturned, (LPOVERLAPPED)&(pSPCB->MonitorDevice)) ;
} else {
dwSetMask |= (pSPCB->dwMonitorDSRMask) ; // Only monitor DSR if it is used.
if (dwSetMask == 0) return (SUCCESS) ; // do not set wait mask.
if (dwModemStatus == pSPCB->dwPreviousModemStatus) { //DbgPrint("PortTestSignalState: Modemstatus hasn't changed\n");
return SUCCESS; } else pSPCB->dwPreviousModemStatus = dwModemStatus;
//DbgPrint("PortTestSignalState: Setting mask ox%x\n", dwSetMask);
SetCommMask(hIOPort, dwSetMask);
// Start a new wait on signal lines (DSR and/or DCD)
if (!WaitCommEvent(hIOPort, &(pSPCB->dwEventMask), (LPOVERLAPPED)&(pSPCB->MonitorDevice))) { //DbgPrint("PortTestSignalState: WaitCommEvent. %d\n", GetLastError());
} }
return(SUCCESS); }
//* PortConnect ------------------------------------------------------------
//
// Function: This API is called when a connection has been completed and some
// steps need to be taken, If bWaitForDevice is set then we monitor DCD only
// else,
// It in turn calls the asyncmac device driver in order to
// indicate to asyncmac that the port and the connection
// over it are ready for commumication.
//
// pdwCompressionInfo is an output only parameter which
// indicates the type(s) of compression supported by the MAC.
//
// bWaitForDevice is set to TRUE when we just want to start monitoring DCD
//
// Returns: SUCCESS
// ERROR_PORT_NOT_OPEN
// ERROR_NO_CONNECTION
// Values returned by GetLastError()
//
//*
DWORD APIENTRY PortConnect(HANDLE hIOPort, BOOL bWaitForDevice, HANDLE *pRasEndpoint) { ASYMAC_OPEN AsyMacOpen; ASYMAC_DCDCHANGE A ; SERIALPCB *pSPCB; BOOL bPadDevice; DWORD dwModemStatus, dwBytesReturned; TCHAR szDeviceType[RAS_MAXLINEBUFLEN];
// This is a special mode of PortConnect where all we do is start monitoring DCD
// Hand off to asyncmac does not happen till the next call to port connect where the
// bWaitForDevice flag is false
//
if (bWaitForDevice) {
pSPCB = FindPortInList(hIOPort, NULL);
if (pSPCB == NULL) { gLastError = ERROR_PORT_NOT_OPEN; return ERROR_NO_CONNECTION ; }
if (!GetCommModemStatus(hIOPort, &dwModemStatus)) return(GetLastError());
// UPDATE the DSR monitoring
//
if (!(dwModemStatus & MS_DSR_ON)) pSPCB->dwMonitorDSRMask = 0 ; else pSPCB->dwMonitorDSRMask = EV_DSR ;
// Tell serial driver to signal rasman if DCD, (and DSR, if it was used) drop
//
//DbgPrint("PortConnect: Setting mask to 0x%x\n",EV_RLSD | (pSPCB->dwMonitorDSRMask));
if (!SetCommMask(hIOPort, EV_RLSD | (pSPCB->dwMonitorDSRMask))) return(GetLastError());
WaitCommEvent(hIOPort, &(pSPCB->dwEventMask), (LPOVERLAPPED) &(pSPCB->MonitorDevice)) ;
return SUCCESS ; }
// Else we do both - change DCD monitoring and handing off context to asyncmac
//
memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
try {
DebugPrintf(("PortConnect\n"));
// Find port in list
pSPCB = FindPortInList(hIOPort, NULL);
if (pSPCB == NULL) { gLastError = ERROR_PORT_NOT_OPEN; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); }
//Make sure connection is still up
if (!GetCommModemStatus(hIOPort, &dwModemStatus)) return(GetLastError());
// Make sure that DSR is still up (if it ever was up!)
if ((!(dwModemStatus & MS_DSR_ON)) && (pSPCB->dwMonitorDSRMask)) { OutputDebugString ("DSR down!!!\r\n") ; return(ERROR_NO_CONNECTION); //Device is down
}
if (!(dwModemStatus & MS_RLSD_ON) ) { OutputDebugString ("DCD down!!!\r\n") ; return(ERROR_NO_CONNECTION); //DCD is down
}
// // UPDATE the DSR monitoring
// //
// if ( ! (dwModemStatus & MS_DSR_ON)) {
// pSPCB->dwMonitorDSRMask = 0 ;
// } else {
// pSPCB->dwMonitorDSRMask = EV_DSR ;
// }
//
// // Tell system to signal rasman if DCD, (and DSR, if it was used) drop
//
// if (!SetCommMask(hIOPort, EV_RLSD | (pSPCB->dwMonitorDSRMask)))
// return(GetLastError());
//
// WaitCommEvent(hIOPort,
// &(pSPCB->dwEventMask),
// &(pSPCB->MonitorDevice)) ;
//Put endpoint in Serial PCB for later use by PortDisconnect
//Find if device type is Pad
GetValueFromFile(pSPCB->szPortName, SER_DEVICETYPE_KEY, szDeviceType, RAS_MAXLINEBUFLEN);
bPadDevice = (_stricmp(szDeviceType, MXS_PAD_TXT) == 0);
// Let the ASYMAC notify us of DCD and DSR change
//
//DbgPrint("PortConnect: Setting mask to 0\n");
if (!SetCommMask(hIOPort, 0)) // Set mask to stop monitoring DCD
return(GetLastError());
//Open AsyncMac (Hand off port to AsyncMac)
AsyMacOpen.hNdisEndpoint = INVALID_HANDLE_VALUE ; AsyMacOpen.LinkSpeed = (atoi(pSPCB->szCarrierBPS) == 0) ? 14400 : atoi(pSPCB->szCarrierBPS) ; AsyMacOpen.FileHandle = hIOPort;
if (bPadDevice || pSPCB->bErrorControlOn) AsyMacOpen.QualOfConnect = (UINT)NdisWanErrorControl; else AsyMacOpen.QualOfConnect = (UINT)NdisWanRaw;
if (!DeviceIoControl(pSPCB->hAsyMac, IOCTL_ASYMAC_OPEN, &AsyMacOpen, sizeof(AsyMacOpen), &AsyMacOpen, sizeof(AsyMacOpen), &dwBytesReturned, &overlapped)) { // Clear the stored end point, so that if it failed to open
// no attempt will be made to close it.
pSPCB->uRasEndpoint = INVALID_HANDLE_VALUE; return(GetLastError()); } else pSPCB->uRasEndpoint = AsyMacOpen.hNdisEndpoint;
*pRasEndpoint = AsyMacOpen.hNdisEndpoint ;
//DbgPrint("PortConnect: RasEndpoint = 0x%x\n", *pRasEndpoint);
A.hNdisEndpoint = (HANDLE) *pRasEndpoint ; A.MacAdapter = NULL ; if (!DeviceIoControl(pSPCB->hAsyMac, IOCTL_ASYMAC_DCDCHANGE, &A, sizeof(A), &A, sizeof(A), &dwBytesReturned, (LPOVERLAPPED)&(pSPCB->MonitorDevice))) { ;//DbgPrint("PortConnect: DeviceIoControl (IOCTL_ASYMAC_DCDCHANGE) failed. %d\n",
// GetLastError());
}
PortClearStatistics(hIOPort);
// if (!(dwModemStatus & MS_RLSD_ON))
// return(PENDING); //DCD is down
// else
return(SUCCESS);
} except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH) { return(gLastError); } }
//* PortDisconnect ---------------------------------------------------------
//
// Function: This API is called to drop a connection and close AsyncMac.
//
// Returns: SUCCESS
// PENDING
// ERROR_PORT_NOT_OPEN
//
//*
DWORD APIENTRY PortDisconnect(HANDLE hIOPort) { ASYMAC_CLOSE AsyMacClose; SERIALPCB *pSPCB; DWORD dwModemStatus, dwBytesReturned; DWORD retcode ; DWORD dwSetMask = 0; DWORD fdwAction = PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR;
memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
try {
DebugPrintf(("PortDisconnect\n"));
//Signal other end of link that connection is being dropped
if (!EscapeCommFunction(hIOPort, CLRDTR)) { ;//DbgPrint("PortDisconnect: EscapeCommFunction Failed. %d\n", GetLastError());
} //
// Apparently, DTR isn't really down
// yet, even though this call is supposed
// to be synchronous to the serial driver.
// We sleep here for a while to make sure
// DTR drops.
//
Sleep(100);
//Find port in list
if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL) { gLastError = ERROR_PORT_NOT_OPEN; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); }
if (pSPCB->uRasEndpoint != INVALID_HANDLE_VALUE) { // Update statistics before closing Asyncmac
if ((retcode = UpdateStatistics(pSPCB)) != SUCCESS) { gLastError = retcode; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); }
//Close AsynacMac
AsyMacClose.MacAdapter = NULL; AsyMacClose.hNdisEndpoint = (HANDLE) pSPCB->uRasEndpoint;
DeviceIoControl(pSPCB->hAsyMac, IOCTL_ASYMAC_CLOSE, &AsyMacClose, sizeof(AsyMacClose), &AsyMacClose, sizeof(AsyMacClose), &dwBytesReturned, &overlapped);
pSPCB->uRasEndpoint = INVALID_HANDLE_VALUE; }
PurgeComm(hIOPort, fdwAction) ; // flush the ports
//Check whether DCD has dropped yet
GetCommModemStatus(hIOPort, &dwModemStatus);
if (dwModemStatus & MS_RLSD_ON) {
//DbgPrint("PortDisconnect: DCD hasn't dropped yet!\n");
dwSetMask = EV_RLSD ; retcode = PENDING ; // not yet dropped.
} else retcode = SUCCESS ;
// UPDATE the DSR monitoring: this restores the DCR to what it was when
// the port was opened.
//
pSPCB->dwMonitorDSRMask = pSPCB->dwActiveDSRMask ;
dwSetMask |= (pSPCB->dwMonitorDSRMask) ;
if (dwSetMask != 0) { // set only if mask is not 0
//DbgPrint("PortDisconnect: Setting mask to 0x%x\n", dwSetMask);
SetCommMask (hIOPort, dwSetMask); if (!WaitCommEvent(hIOPort, &(pSPCB->dwEventMask), (LPOVERLAPPED)&(pSPCB->MonitorDevice))) { //DbgPrint("PortDisconnect: WaitCommEvent. %d\n", GetLastError());
} }
//Since DCD may have dropped after GetCommModemStatus and
// before WaitCommEvent, check it again.
if (retcode != SUCCESS) { GetCommModemStatus(hIOPort, &dwModemStatus);
if (dwModemStatus & MS_RLSD_ON) { //DbgPrint("PortDisconnect: DCD hasn't dropped yet. 2\n");
retcode = PENDING ; // not yet dropped.
} else retcode = SUCCESS ; }
// Set the default connect baud
//
SetCommDefaults(pSPCB->hIOPort, pSPCB->szPortName);
} except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH) { return(gLastError); }
return retcode ; }
//* PortInit ---------------------------------------------------------------
//
// Function: This API re-initializes the com port after use.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_CONFIGURED
// ERROR_DEVICE_NOT_READY
//
//*
DWORD APIENTRY PortInit(HANDLE hIOPort) { DWORD fdwAction = PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR; DWORD dwErrors; SERIALPCB *pSPCB;
DebugPrintf(("PortInit\n"));
pSPCB = FindPortInList(hIOPort, NULL) ;
// Raise DTR
if (!EscapeCommFunction(hIOPort, SETDTR)) return(GetLastError());
if (!PurgeComm(hIOPort, fdwAction)) return(GetLastError());
if (!ClearCommError(hIOPort, &dwErrors, NULL)) return(GetLastError());
// Reset szCarrierBPS to MAXCARRIERBPS from ini file
//
InitCarrierBps(pSPCB->szPortName, pSPCB->szCarrierBPS);
return(SUCCESS); }
//* PortSend ---------------------------------------------------------------
//
// Function: This API sends a buffer to the port. This API is
// asynchronous and normally returns PENDING; however, if
// WriteFile returns synchronously, the API will return
// SUCCESS.
//
// Returns: SUCCESS
// PENDING
// Return code from GetLastError
//
//*
DWORD PortSend(HANDLE hIOPort, BYTE *pBuffer, DWORD dwSize) { SERIALPCB *pSPCB; DWORD dwRC, pdwBytesWritten; BOOL bIODone;
DebugPrintf(("PortSend\n"));
// Find the SerialPCB which contains hIOPOrt
pSPCB = FindPortInList(hIOPort, NULL);
if (pSPCB == NULL) return(ERROR_PORT_NOT_OPEN);
// Send Buffer to Port
bIODone = WriteFile(hIOPort, pBuffer, dwSize, &pdwBytesWritten, //pdwBytesWritten is not used
(LPOVERLAPPED)&(pSPCB->SendReceive));
if (bIODone) return(PENDING);
else if ((dwRC = GetLastError()) == ERROR_IO_PENDING) return(PENDING);
else return(dwRC); }
//* PortReceive ------------------------------------------------------------
//
// Function: This API reads from the port. This API is
// asynchronous and normally returns PENDING; however, if
// ReadFile returns synchronously, the API will return
// SUCCESS.
//
// Returns: SUCCESS
// PENDING
// Return code from GetLastError
//
//*
DWORD PortReceive(HANDLE hIOPort, BYTE *pBuffer, DWORD dwSize, DWORD dwTimeOut) { COMMTIMEOUTS CT; SERIALPCB *pSPCB; DWORD dwRC, pdwBytesRead; BOOL bIODone;
DebugPrintf(("PortReceive\n"));
// Find the SerialPCB which contains hIOPOrt
pSPCB = FindPortInList(hIOPort, NULL);
if (pSPCB == NULL) return(ERROR_PORT_NOT_OPEN);
// Set Read Timeouts
CT.ReadIntervalTimeout = 0; CT.ReadTotalTimeoutMultiplier = 0; CT.ReadTotalTimeoutConstant = dwTimeOut;
if ( ! SetCommTimeouts(hIOPort, &CT)) return(GetLastError());
// Read from Port
bIODone = ReadFile(hIOPort, pBuffer, dwSize, &pdwBytesRead, //pdwBytesRead is not used
(LPOVERLAPPED)&(pSPCB->SendReceive));
if (bIODone) { return(PENDING); }
else if ((dwRC = GetLastError()) == ERROR_IO_PENDING) return(PENDING);
else return(dwRC); }
//* PortReceiveComplete ------------------------------------------------------
//
// Function: Completes a read - if still PENDING it cancels it - else it returns the bytes read.
// PortClearStatistics.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_OPEN
//*
DWORD PortReceiveComplete (HANDLE hIOPort, PDWORD bytesread) { SERIALPCB *pSPCB;
// Find the SerialPCB which contains hIOPOrt
pSPCB = FindPortInList(hIOPort, NULL);
if (pSPCB == NULL) return(ERROR_PORT_NOT_OPEN);
if (!GetOverlappedResult(hIOPort, (LPOVERLAPPED)&(pSPCB->SendReceive), bytesread, FALSE)) { #if DBG
DbgPrint("PortReceiveComplete: GetOverlappedResult failed. %d", GetLastError()); #endif
PurgeComm (hIOPort, PURGE_RXABORT) ; *bytesread = 0 ; }
return SUCCESS ; }
//* PortCompressionSetInfo -------------------------------------------------
//
// Function: This API selects Asyncmac compression mode by setting
// Asyncmac's compression bits.
//
// Returns: SUCCESS
// Return code from GetLastError
//
//*
DWORD PortCompressionSetInfo(HANDLE hIOPort) {
// Not supported anymore -
return(SUCCESS); }
//* PortClearStatistics ----------------------------------------------------
//
// Function: This API is used to mark the beginning of the period for which
// statistics will be reported. The current numbers are copied
// from the MAC and stored in the Serial Port Control Block. At
// the end of the period PortGetStatistics will be called to
// compute the difference.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_OPEN
//*
DWORD PortClearStatistics(HANDLE hIOPort) { #if 0
ASYMAC_GETSTATS A; int i; DWORD dwBytesReturned; SERIALPCB *pSPCB;
memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
DebugPrintf(("PortClearStatistics\n"));
// Find port in list
if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL) return(ERROR_PORT_NOT_OPEN);
// Check whether Asyncmac is open
if (pSPCB->uRasEndpoint == INVALID_RASENDPOINT)
for (i=0; i<NUM_RAS_SERIAL_STATS; i++) // Asymac is closed
pSPCB->Stats[i] = 0;
else // Asyncmac is open
{ // Fill in GetStats struct
A.MacAdapter = NULL; A.hNdisEndpoint = pSPCB->uRasEndpoint;
// Call Asymac
if (!DeviceIoControl(pSPCB->hAsyMac, IOCTL_ASYMAC_GETSTATS, &A, sizeof(A), &A, sizeof(A), &dwBytesReturned, &overlapped)) return(GetLastError());
// Update Stats in Serial Port Control Block
pSPCB->Stats[BYTES_XMITED] = A.AsyMacStats.GenericStats.BytesTransmitted; pSPCB->Stats[BYTES_RCVED] = A.AsyMacStats.GenericStats.BytesReceived; pSPCB->Stats[FRAMES_XMITED] = A.AsyMacStats.GenericStats.FramesTransmitted; pSPCB->Stats[FRAMES_RCVED] = A.AsyMacStats.GenericStats.FramesReceived;
pSPCB->Stats[CRC_ERR] = A.AsyMacStats.SerialStats.CRCErrors; pSPCB->Stats[TIMEOUT_ERR] = A.AsyMacStats.SerialStats.TimeoutErrors; pSPCB->Stats[ALIGNMENT_ERR] = A.AsyMacStats.SerialStats.AlignmentErrors; pSPCB->Stats[SERIAL_OVERRUN_ERR] = A.AsyMacStats.SerialStats.SerialOverrunErrors; pSPCB->Stats[FRAMING_ERR] = A.AsyMacStats.SerialStats.FramingErrors; pSPCB->Stats[BUFFER_OVERRUN_ERR] = A.AsyMacStats.SerialStats.BufferOverrunErrors;
pSPCB->Stats[BYTES_XMITED_UNCOMP] = A.AsyMacStats.CompressionStats.BytesTransmittedUncompressed;
pSPCB->Stats[BYTES_RCVED_UNCOMP] = A.AsyMacStats.CompressionStats.BytesReceivedUncompressed;
pSPCB->Stats[BYTES_XMITED_COMP] = A.AsyMacStats.CompressionStats.BytesTransmittedCompressed;
pSPCB->Stats[BYTES_RCVED_COMP] = A.AsyMacStats.CompressionStats.BytesReceivedCompressed; } #endif
return(SUCCESS); }
//* PortGetStatistics ------------------------------------------------------
//
// Function: This API reports MAC statistics since the last call to
// PortClearStatistics.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_OPEN
//*
DWORD PortGetStatistics(HANDLE hIOPort, RAS_STATISTICS *pStat) { #if 0
ASYMAC_GETSTATS A; DWORD dwBytesReturned; SERIALPCB *pSPCB;
memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
DebugPrintf(("PortGetStatistics\n"));
// Find port in list
if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL) return(ERROR_PORT_NOT_OPEN);
// Check whether Asyncmac is open
if (pSPCB->uRasEndpoint == INVALID_RASENDPOINT) { // Asyncmac is closed
// Report current counts
pStat->S_NumOfStatistics = NUM_RAS_SERIAL_STATS;
pStat->S_Statistics[BYTES_XMITED] = pSPCB->Stats[BYTES_XMITED]; pStat->S_Statistics[BYTES_RCVED] = pSPCB->Stats[BYTES_RCVED]; pStat->S_Statistics[FRAMES_XMITED] = pSPCB->Stats[FRAMES_XMITED]; pStat->S_Statistics[FRAMES_RCVED] = pSPCB->Stats[FRAMES_RCVED];
pStat->S_Statistics[CRC_ERR] = pSPCB->Stats[CRC_ERR]; pStat->S_Statistics[TIMEOUT_ERR] = pSPCB->Stats[TIMEOUT_ERR]; pStat->S_Statistics[ALIGNMENT_ERR] = pSPCB->Stats[ALIGNMENT_ERR]; pStat->S_Statistics[SERIAL_OVERRUN_ERR] = pSPCB->Stats[SERIAL_OVERRUN_ERR]; pStat->S_Statistics[FRAMING_ERR] = pSPCB->Stats[FRAMING_ERR]; pStat->S_Statistics[BUFFER_OVERRUN_ERR] = pSPCB->Stats[BUFFER_OVERRUN_ERR];
pStat->S_Statistics[BYTES_XMITED_UNCOMP]= pSPCB->Stats[BYTES_XMITED_UNCOMP]; pStat->S_Statistics[BYTES_RCVED_UNCOMP] = pSPCB->Stats[BYTES_RCVED_UNCOMP]; pStat->S_Statistics[BYTES_XMITED_COMP] = pSPCB->Stats[BYTES_XMITED_COMP]; pStat->S_Statistics[BYTES_RCVED_COMP] = pSPCB->Stats[BYTES_RCVED_COMP]; } else { // Asyncmac is open
// Fill in GetStats struct
A.MacAdapter = NULL; A.hNdisEndpoint = pSPCB->uRasEndpoint;
// Call Asymac to get current MAC statistics counts
if (!DeviceIoControl(pSPCB->hAsyMac, IOCTL_ASYMAC_GETSTATS, &A, sizeof(A), &A, sizeof(A), &dwBytesReturned, &overlapped)) return(GetLastError());
// Find difference between last PortClearStatistics and current counts
pStat->S_NumOfStatistics = NUM_RAS_SERIAL_STATS;
pStat->S_Statistics[BYTES_XMITED] = A.AsyMacStats.GenericStats.BytesTransmitted - pSPCB->Stats[BYTES_XMITED];
pStat->S_Statistics[BYTES_RCVED] = A.AsyMacStats.GenericStats.BytesReceived - pSPCB->Stats[BYTES_RCVED];
pStat->S_Statistics[FRAMES_XMITED] = A.AsyMacStats.GenericStats.FramesTransmitted - pSPCB->Stats[FRAMES_XMITED];
pStat->S_Statistics[FRAMES_RCVED] = A.AsyMacStats.GenericStats.FramesReceived - pSPCB->Stats[FRAMES_RCVED];
pStat->S_Statistics[CRC_ERR] = A.AsyMacStats.SerialStats.CRCErrors - pSPCB->Stats[CRC_ERR];
pStat->S_Statistics[TIMEOUT_ERR] = A.AsyMacStats.SerialStats.TimeoutErrors - pSPCB->Stats[TIMEOUT_ERR];
pStat->S_Statistics[ALIGNMENT_ERR] = A.AsyMacStats.SerialStats.AlignmentErrors - pSPCB->Stats[ALIGNMENT_ERR];
pStat->S_Statistics[SERIAL_OVERRUN_ERR] = A.AsyMacStats.SerialStats.SerialOverrunErrors - pSPCB->Stats[SERIAL_OVERRUN_ERR];
pStat->S_Statistics[FRAMING_ERR] = A.AsyMacStats.SerialStats.FramingErrors - pSPCB->Stats[FRAMING_ERR];
pStat->S_Statistics[BUFFER_OVERRUN_ERR] = A.AsyMacStats.SerialStats.BufferOverrunErrors - pSPCB->Stats[BUFFER_OVERRUN_ERR];
pStat->S_Statistics[BYTES_XMITED_UNCOMP] = A.AsyMacStats.CompressionStats.BytesTransmittedUncompressed - pSPCB->Stats[BYTES_XMITED_UNCOMP];
pStat->S_Statistics[BYTES_RCVED_UNCOMP] = A.AsyMacStats.CompressionStats.BytesReceivedUncompressed - pSPCB->Stats[BYTES_RCVED_UNCOMP];
pStat->S_Statistics[BYTES_XMITED_COMP] = A.AsyMacStats.CompressionStats.BytesTransmittedCompressed - pSPCB->Stats[BYTES_XMITED_COMP];
pStat->S_Statistics[BYTES_RCVED_COMP] = A.AsyMacStats.CompressionStats.BytesReceivedCompressed - pSPCB->Stats[BYTES_RCVED_COMP]; } #endif
return(SUCCESS); }
//* PortSetFraming -------------------------------------------------------
//
// Function: Sets the framing type with the mac
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY PortSetFraming(HANDLE hIOPort, DWORD SendFeatureBits, DWORD RecvFeatureBits, DWORD SendBitMask, DWORD RecvBitMask) { #if 0
ASYMAC_STARTFRAMING A; DWORD dwBytesReturned; SERIALPCB *pSPCB;
memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
// Find port in list
if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL) return(ERROR_PORT_NOT_OPEN);
A.MacAdapter = NULL ; A.hNdisEndpoint = pSPCB->uRasEndpoint; A.SendFeatureBits = SendFeatureBits; A.RecvFeatureBits = RecvFeatureBits; A.SendBitMask = SendBitMask; A.RecvBitMask = RecvBitMask;
if (!DeviceIoControl(pSPCB->hAsyMac, IOCTL_ASYMAC_STARTFRAMING, &A, sizeof(A), &A, sizeof(A), &dwBytesReturned, &overlapped)) return(GetLastError()); #endif
return(SUCCESS); }
//* PortGetPortState -------------------------------------------------------
//
// Function: This API is used in MS-DOS only.
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY PortGetPortState(char *pszPortName, DWORD *pdwUsage) { DebugPrintf(("PortGetPortState\n"));
return(SUCCESS); }
//* PortChangeCallback -----------------------------------------------------
//
// Function: This API is used in MS-DOS only.
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY PortChangeCallback(HANDLE hIOPort) { DebugPrintf(("PortChangeCallback\n"));
return(SUCCESS); }
DWORD APIENTRY PortSetINetCfg(PVOID pvINetCfg) { ((void) pvINetCfg);
return SUCCESS; }
DWORD APIENTRY PortSetIoCompletionPort ( HANDLE hIoCompletionPort) { ((void) hIoCompletionPort);
return SUCCESS; }
|