📄 mac.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*****************************************************************************
*
*
* @doc EX_RAS
* mac.c Mac Layer interface
*
* Date: 2/25/99
*
*/
// Include Files
#include "windows.h"
#include "ndis.h"
#include "ras.h"
#include "raserror.h"
#include "cxport.h"
#include "protocol.h"
#include "ppp.h"
#include "macp.h"
#define TAPI_DEVICECLASS_NAME TEXT("tapi/line")
// ----------------------------------------------------------------
//
// Global Data
//
// ----------------------------------------------------------------
NDIS_HANDLE v_PROTHandle; // Our NDIS protocol handle.
HANDLE v_hRequestEvent;
CRITICAL_SECTION v_RequestCS;
NDIS_STATUS v_RequestStatus;
PNDISWAN_ADAPTER v_AdapterList;
CRITICAL_SECTION v_AdapterCS;
DWORD
pppMac_NdisToRasErrorCode(
DWORD dwNdisErrorCode)
//
// Translate an NDIS error code returned by the miniport driver
// into a RAS error code.
//
{
DWORD dwRasErrorCode;
switch(dwNdisErrorCode)
{
case NDIS_STATUS_SUCCESS:
dwRasErrorCode = ERROR_SUCCESS;
break;
case NDIS_STATUS_CLOSED:
dwRasErrorCode = ERROR_PORT_NOT_OPEN;
break;
case NDIS_STATUS_TAPI_CALLUNAVAIL:
case NDIS_STATUS_TAPI_RESOURCEUNAVAIL:
dwRasErrorCode = ERROR_PORT_NOT_AVAILABLE;
break;
case NDIS_STATUS_FAILURE:
case NDIS_STATUS_INVALID_OID:
dwRasErrorCode = ERROR_UNKNOWN;
break;
case NDIS_STATUS_TAPI_INVALPARAM:
dwRasErrorCode = ERROR_WRONG_INFO_SPECIFIED;
break;
case NDIS_STATUS_TAPI_NODEVICE:
dwRasErrorCode = ERROR_DEVICE_NOT_READY;
break;
case NDIS_STATUS_TAPI_NODRIVER:
dwRasErrorCode = ERROR_DEVICE_NOT_READY;
break;
case NDIS_STATUS_TAPI_OPERATIONUNAVAIL:
dwRasErrorCode = ERROR_DEVICE_NOT_READY;
break;
case NDIS_STATUS_RESOURCES:
dwRasErrorCode = ERROR_NOT_ENOUGH_MEMORY;
break;
case NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION:
dwRasErrorCode = ERROR_UNKNOWN;
break;
case NDIS_STATUS_TAPI_INVALLINESTATE:
dwRasErrorCode = ERROR_PORT_NOT_CONFIGURED;
break;
case NDIS_STATUS_TAPI_INUSE:
dwRasErrorCode = ERROR_PORT_ALREADY_OPEN;
break;
default:
//
// All error types that the miniport returns should be
// covered explicitly. If any are not, they will be caught here
// and can have a case added.
//
DEBUGMSG(ZONE_ERROR, (TEXT("PPP: pppMac_NdisToRasErrorCode doesn't know error %x\n"), dwNdisErrorCode));
dwRasErrorCode = ERROR_UNKNOWN;
break;
}
return dwRasErrorCode;
}
DWORD
pppMac_Initialize()
{
DWORD dwRetVal;
DEBUGMSG (ZONE_TRACE, (TEXT("+pppMac_Initialize\r\n")));
v_hRequestEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
InitializeCriticalSection (&v_RequestCS);
InitializeCriticalSection (&v_AdapterCS);
if (dwRetVal = DoNDISRegisterProtocol())
{
CloseHandle (v_hRequestEvent);
return dwRetVal;
}
// Note that adapters are dynamically bound via the
// PROTBindAdapter callback. No static initialization
// takes place here.
return SUCCESS;
}
#define COUNTOF(array) (sizeof(array) / sizeof(array[0]))
DWORD
pppMac_InstanceCreate (
void *SessionContext,
void **ReturnedContext,
LPCTSTR szDeviceName,
LPCTSTR szDeviceType)
{
NDIS_STATUS Status;
macCntxt_t *pMac;
DEBUGMSG (ZONE_FUNCTION, (TEXT("!pppMac_InstanceCreate devName=%s devType=%s\n"), szDeviceName, szDeviceType));
// Allocate our context structure.
pMac = (macCntxt_t *)pppAllocateMemory(sizeof (macCntxt_t));
if (NULL == pMac) {
return ERROR_NOT_ENOUGH_MEMORY;
}
pMac->session = SessionContext;
pMac->bCallCloseRequested = FALSE;
pMac->bCallClosed = TRUE;
pMac->bLineCloseRequested = FALSE;
pMac->bLineClosed = TRUE;
pMac->bMacStatsObtained = FALSE;
pMac->dwLineCallState = LINECALLSTATE_IDLE;
StringCchCopyW(pMac->szDeviceName, COUNTOF(pMac->szDeviceName), szDeviceName);
StringCchCopyW(pMac->szDeviceType, COUNTOF(pMac->szDeviceType), szDeviceType);
(NDIS_HANDLE)pMac->hCall = INVALID_HANDLE_VALUE;
(NDIS_HANDLE)pMac->hLine = INVALID_HANDLE_VALUE;
if (SUCCESS != FindAdapter (szDeviceName, szDeviceType, &(pMac->pAdapter),
&(pMac->dwDeviceID))) {
DEBUGMSG (ZONE_ERROR, (TEXT("PPP: Can't find device '%s'\n"), szDeviceName));
pppFreeMemory (pMac, sizeof (macCntxt_t));
return ERROR_DEVICE_DOES_NOT_EXIST;
}
//
// Do not allow new connections on an adapter from which we are unbinding.
//
if (pMac->pAdapter->bClosingAdapter)
{
DEBUGMSG (ZONE_ERROR, (TEXT("PPP: No new connections on '%s' allowed due to adapter close in progress\n"), pMac->szDeviceName));
AdapterDelRef(pMac->pAdapter);
pppFreeMemory (pMac, sizeof (macCntxt_t));
return ERROR_DEVICE_DOES_NOT_EXIST;
}
DEBUGMSG (ZONE_TRACE, (TEXT("pppMac_InstanceCreate: Found DeviceID %d\r\n"),
pMac->dwDeviceID));
pMac->pPendingLineCloseCompleteList = NULL;
pMac->pPendingCallDropCompleteList = NULL;
pMac->pPendingCallCloseCompleteList = NULL;
PppNdisDoSyncRequest (&Status,
pMac->pAdapter,
NdisRequestQueryInformation,
OID_WAN_GET_INFO,
&(pMac->WanInfo),
sizeof(pMac->WanInfo));
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGMSG (ZONE_ERROR,
(TEXT(" pppMac_InstanceCreate: Error 0x%X from OID_WAN_GET_INFO\r\n"),
Status));
AdapterDelRef (pMac->pAdapter);
pppFreeMemory (pMac, sizeof (macCntxt_t));
return ERROR_DEVICE_DOES_NOT_EXIST;
}
pMac->hNdisTapiEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
pMac->hEventLineOpenComplete = CreateEvent (NULL, TRUE, FALSE, NULL);
if (pMac->hNdisTapiEvent == NULL || pMac->hEventLineOpenComplete == NULL)
{
DEBUGMSG (ZONE_ERROR, (TEXT("PPP: ERROR - pppMac_InstanceCreate CreateEvent failed\n")));
return ERROR_NOT_ENOUGH_MEMORY;
}
NdisAllocateSpinLock (&pMac->PacketLock);
Status = NdisWanAllocateSendResources (pMac);
if (NDIS_STATUS_SUCCESS != Status) {
// This will do the AdapterDelRef()
pppMac_InstanceDelete (pMac);
return Status;
}
*ReturnedContext = pMac;
DEBUGMSG(ZONE_MAC, (L"PPP: Created MAC %x adapter=%s %x refcnt=%d\n", pMac, pMac->pAdapter->szAdapterName, pMac->pAdapter, pMac->pAdapter->dwRefCnt));
return 0;
}
void
pppMac_GetFramingInfo(
IN PVOID context,
OUT PDWORD pFramingBits,
OUT PDWORD pDesiredACCM)
{
macCntxt_t *pMac = (macCntxt_t *)context;
*pFramingBits = pMac->WanInfo.FramingBits;
*pDesiredACCM = pMac->WanInfo.DesiredACCM;
}
DWORD
pppMac_LineOpen(
void *context)
{
macCntxt_t *pMac = (macCntxt_t *)context;
DWORD dwRetVal;
// Configure device specific parameter settings, if any
if (((pppSession_t *)(pMac->session))->lpbDevConfig != NULL)
{
NdisTapiSetDevConfig (pMac);
}
// Open the line
dwRetVal = NdisTapiLineOpen (pMac);
return pppMac_NdisToRasErrorCode(dwRetVal);
}
DWORD
pppMac_LineListen(
void *context)
//
// Listen for incoming connections on the specified line.
//
{
macCntxt_t *pMac = (macCntxt_t *)context;
DWORD dwRetVal;
dwRetVal = NdisTapiSetDefaultMediaDetection(pMac, LINEMEDIAMODE_DIGITALDATA | LINEMEDIAMODE_DATAMODEM);
return pppMac_NdisToRasErrorCode(dwRetVal);
}
static void
pppHangupComplete(
PVOID pData)
{
HANDLE hHangupCompleteEvent = (HANDLE)pData;
DEBUGMSG( ZONE_FUNCTION, ( TEXT( "PPP:+pppHangupComplete\n" ) ));
SetEvent(hHangupCompleteEvent);
DEBUGMSG( ZONE_FUNCTION, ( TEXT( "PPP:-pppHangupComplete\n" ) ));
}
//
// Custom Scripting Dll Support functions
//
DWORD
RasGetBuffer(
OUT PBYTE * ppBuffer,
IN OUT PDWORD pdwSize)
//
// The custom-scripting DLL calls RasGetBuffer to allocate memory
// for sending or receiving data over the port connected to the server.
//
// Return values
// If the function succeeds, the return value is ERROR_SUCCESS.
//
// If the function fails, the return value is the following error code.
//
// ERROR_OUT_OF_BUFFERS - RAS cannot allocate anymore buffer space.
//
{
DWORD dwResult = ERROR_SUCCESS;
// To simplify buffer management, always allocate max size buffers.
*pdwSize = MAX_CUSTOM_SCRIPT_RX_BUFFER_SIZE;
*ppBuffer = pppAllocateMemory(*pdwSize);
if (*ppBuffer == NULL)
{
dwResult = ERROR_OUT_OF_BUFFERS;
DEBUGMSG( ZONE_FUNCTION, ( TEXT( "PPP:ERROR in RasGetBuffer %d byte alloc, error = %x\n" ), *pdwSize, GetLastError() ));
}
return dwResult;
}
DWORD
RasFreeBuffer(
IN PBYTE pBuffer)
//
// The custom-scripting DLL calls RasFreeBuffer to release a
// memory buffer that was allocated by a previous call to RasGetBuffer
//
// Return values
// If the function succeeds, the return value is ERROR_SUCCESS.
//
// If the function fails, the return value is the following error code.
//
// ERROR_BUFFER_INVALID - The pointer to the buffer passed in the
// pBuffer parameter is invalid.
//
{
DWORD dwResult = ERROR_SUCCESS;
pppFreeMemory(pBuffer, MAX_CUSTOM_SCRIPT_RX_BUFFER_SIZE);
return dwResult;
}
DWORD
RasSendBuffer(
IN HANDLE hPort,
IN PBYTE pBuffer,
IN DWORD dwSize)
//
// The custom-scripting DLL calls the RasSendBuffer function
// to send data to the server over the specified port.
//
// Return values
// If the function succeeds, the return value is ERROR_SUCCESS.
// If the function fails, the return value can be one of the following error codes.
//
// Value Meaning
// ERROR_BUFFER_INVALID The pointer to the buffer passed in the pBuffer parameter is invalid.
// ERROR_INVALID_PORT_HANDLE The handle specified by the hPort parameter is invalid.
//
{
macCntxt_t *pMac = (macCntxt_t *)hPort;
DWORD dwResult = ERROR_SUCCESS,
dwBytesSent,
bytesWritten;
for (dwBytesSent = 0;
dwBytesSent < dwSize;
dwBytesSent += bytesWritten)
{
if (!WriteFile (pMac->hComPort, pBuffer + dwBytesSent, dwSize - dwBytesSent, &bytesWritten, 0)
|| bytesWritten == 0)
{
dwResult = GetLastError();
DEBUGMSG(ZONE_ERROR, (
TEXT( "PPP: ERROR RasSendBuffer-WriteFile Error %d Aborting Packet after sending %d of %d bytes\n" ),
dwResult, dwBytesSent, dwSize) );
break;
}
}
return dwResult;
}
DWORD
RasRetrieveBuffer(
IN HANDLE hPort,
OUT PBYTE pBuffer,
OUT PDWORD pdwBytesRead)
//
// The custom-scripting DLL calls the RasRetrieveBuffer function
// to obtain data received from the RAS server over the specified port.
// The custom-scripting DLL should call RasRetrieveBuffer only after
// RAS has signaled the event object passed in the call to RasReceiveBuffer.
//
// Return values
// If the function succeeds, the return value is ERROR_SUCCESS.
//
// If the function fails, the return value can be one of the following error codes.
//
// Value Meaning
// ERROR_BUFFER_INVALID The pointer to the buffer passed in the pBuffer parameter is invalid.
// ERROR_INVALID_PORT_HANDLE The handle specified by the hPort parameter is invalid.
//
{
macCntxt_t *pMac = (macCntxt_t *)hPort;
DWORD dwResult = ERROR_SUCCESS;
if (ReadFile(pMac->hComPort, pBuffer, MAX_CUSTOM_SCRIPT_RX_BUFFER_SIZE, pdwBytesRead, 0 ) == FALSE)
{
// Serial functions will return an error if a PCMCIA card has
// been removed. If the error is INVALID_HANDLE or GEN_FAILURE
// the PCMCIA card was removed. In this case the MAC layer is
// down.
dwResult = GetLastError();
DEBUGMSG(ZONE_ERROR, (TEXT( "PPP:RasRetrieveBuffer ReadFile failed %d\n"), dwResult));
}
return dwResult;
}
DWORD WINAPI
rasReceiveEventThread (
IN LPVOID pVArg)
{
macCntxt_t *pMac = (macCntxt_t *)pVArg;
DWORD dwMask;
DEBUGMSG( ZONE_FUNCTION, (TEXT( "PPP: +rasReceiveEventThread\n") ));
while ( WaitCommEvent(pMac->hComPort, &dwMask, NULL ) == TRUE )
{
if (dwMask & (EV_POWER | EV_RLSD))
{
// Line down
DEBUGMSG(ZONE_ERROR, (TEXT( "PPP:rasReceiveEventThread - LINE DOWN eventmask=%x\n"), dwMask));
}
else if (dwMask & EV_RXCHAR)
{
// Data ready to be read
DEBUGMSG(ZONE_ERROR, (TEXT( "PPP:rasReceiveEventThread - EV_RXCHAR\n"), dwMask));
}
//
// Signal the custom dll script to call RasRetrieveBuffer to read any rx data
//
SetEvent(pMac->hRxEvent);
//
// Paranoia? In case WaitCommEvent returns for pending rx data instead of
// waiting for new rx data.
//
Sleep(50);
}
DEBUGMSG( ZONE_FUNCTION, (TEXT( "PPP: -rasReceiveEventThread\n") ));
return 0;
}
DWORD
RasReceiveBuffer(
IN HANDLE hPort,
OUT PBYTE pBuffer,
OUT PDWORD pdwSize,
IN DWORD dwTimeoutMilliseconds,
IN HANDLE hEvent)
//
// The custom-scripting DLL calls the RasReceiveBuffer function
// to inform RAS that it is ready to receive data from the server over the specified port.
//
// Return values
// If the function succeeds, the return value is ERROR_SUCCESS.
//
// If the function fails, the return value can be one of the following error codes.
//
// Value Meaning
// ERROR_BUFFER_INVALID The pointer to the buffer passed in the pBuffer parameter is invalid.
// ERROR_INVALID_PORT_HANDLE The handle specified by the hPort parameter is invalid.
//
{
macCntxt_t *pMac = (macCntxt_t *)hPort;
DWORD dwResult = ERROR_SUCCESS,
dwID;
COMMTIMEOUTS CommTimeouts;
do
{
if (SetCommMask(pMac->hComPort, EV_RXCHAR | EV_RLSD | EV_POWER ) == FALSE)
{
dwResult = GetLastError();
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -