5205 lines
134 KiB
C
5205 lines
134 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pxtapi.c
|
|
|
|
Abstract:
|
|
|
|
The module contains the TAPI-specific code for the NDIS Proxy.
|
|
|
|
Author:
|
|
|
|
Richard Machin (RMachin)
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
RMachin 01-08-97 created (after Dan Knudson's NdisTapi)
|
|
TonyBe 02-21-99 re-work/re-write
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
#include <stdio.h>
|
|
#define MODULE_NUMBER MODULE_TAPI
|
|
#define _FILENUMBER 'IPAT'
|
|
|
|
ULONG
|
|
GetLineEvents(
|
|
PCHAR EventBuffer,
|
|
ULONG BufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets event data out of our global event queue and writes it to the buffer. Data is put into the queue
|
|
by PxIndicateStatus (above).
|
|
|
|
|
|
Arguments:
|
|
|
|
EventBuffer pointer to a buffer of size BufferSize
|
|
BufferSize size of event buffer (expected to be 1024)
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
Note:
|
|
|
|
Assumes TspEventList.Lock held by caller.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG BytesLeft;
|
|
ULONG BytesMoved = 0;
|
|
|
|
BytesLeft = BufferSize;
|
|
|
|
while (!(IsListEmpty(&TspEventList.List))) {
|
|
|
|
PPROVIDER_EVENT ProviderEvent;
|
|
|
|
if (BytesLeft < sizeof(NDIS_TAPI_EVENT)) {
|
|
break;
|
|
}
|
|
|
|
ProviderEvent = (PPROVIDER_EVENT)
|
|
RemoveHeadList(&TspEventList.List);
|
|
|
|
TspEventList.Count--;
|
|
|
|
RtlMoveMemory(EventBuffer + BytesMoved,
|
|
(PUCHAR)&ProviderEvent->Event,
|
|
sizeof(NDIS_TAPI_EVENT));
|
|
|
|
BytesMoved += sizeof(NDIS_TAPI_EVENT);
|
|
BytesLeft -= sizeof(NDIS_TAPI_EVENT);
|
|
|
|
ExFreeToNPagedLookasideList(&ProviderEventLookaside,
|
|
ProviderEvent);
|
|
}
|
|
|
|
return (BytesMoved);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiMakeCall(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TSPI_lineMakeCall handler.
|
|
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_MAKE_CALL TapiBuffer =
|
|
(PNDIS_TAPI_MAKE_CALL)(pNdisTapiRequest->Data);
|
|
|
|
LINE_CALL_PARAMS* pTapiCallParams =
|
|
(LINE_CALL_PARAMS*)(&TapiBuffer->LineCallParams);
|
|
|
|
PPX_TAPI_LINE TapiLine;
|
|
PPX_TAPI_ADDR TapiAddr;
|
|
PPX_VC pVc = NULL;
|
|
PPX_CL_AF pClAf;
|
|
PCO_CALL_PARAMETERS pNdisCallParams = 0;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
ULONG targetDeviceID = 0;
|
|
LPCWSTR lpcwszTemp;
|
|
PPX_ADAPTER pAdapter;
|
|
PPX_TAPI_PROVIDER TapiProvider;
|
|
|
|
lpcwszTemp = (LPWSTR)
|
|
(((UCHAR *) TapiBuffer) + TapiBuffer->ulDestAddressOffset);
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("TapiMakeCall: DialAddress in Tapi buffer %x = %ls\n",lpcwszTemp, lpcwszTemp));
|
|
|
|
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
|
|
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI,
|
|
("PxTapiMakeCall: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
|
|
|
|
return (NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
do {
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
//
|
|
// Is this line in service? (does it have an valid af?)
|
|
//
|
|
if (!(TapiLine->DevStatus->ulDevStatusFlags &
|
|
LINEDEVSTATUSFLAGS_INSERVICE)) {
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiMakeCall: Line not in service!\n"));
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
Status = NDISTAPIERR_DEVICEOFFLINE;
|
|
break;
|
|
}
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI,
|
|
("PxTapiMakeCall: got device x%x from ID %d\n", TapiLine, TapiBuffer->hdLine));
|
|
|
|
if (pTapiCallParams->ulAddressMode == LINEADDRESSMODE_ADDRESSID) {
|
|
|
|
//
|
|
// Get the specificed address from the address id
|
|
//
|
|
if (!IsAddressValid(TapiLine, pTapiCallParams->ulAddressID, &TapiAddr)) {
|
|
Status = NDISTAPIERR_BADDEVICEID;
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Get the first available address
|
|
//
|
|
TapiAddr =
|
|
GetAvailAddrFromLine(TapiLine);
|
|
|
|
if (TapiAddr == NULL) {
|
|
Status = NDISTAPIERR_BADDEVICEID;
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
break;
|
|
}
|
|
}
|
|
|
|
TapiProvider = TapiLine->TapiProvider;
|
|
pAdapter = TapiProvider->Adapter;
|
|
pClAf = TapiLine->ClAf;
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
|
|
//
|
|
// Allocate a Vc block. This will create the block
|
|
// with refcount = 1.
|
|
//
|
|
pVc = PxAllocateVc(pClAf);
|
|
|
|
if (pVc == NULL) {
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiMakeCall: failed to allocate a vc\n"));
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
|
|
break;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
|
|
Status =
|
|
AllocateTapiCallInfo(pVc, NULL);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiMakeCall: Error allocating TapiCallInfo!\n"));
|
|
PxFreeVc(pVc);
|
|
Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
|
|
break;
|
|
}
|
|
|
|
pVc->TapiLine = TapiLine;
|
|
pVc->TapiAddr = TapiAddr;
|
|
InterlockedIncrement((PLONG)&TapiAddr->CallCount);
|
|
InterlockedIncrement((PLONG)&TapiLine->DevStatus->ulNumActiveCalls);
|
|
|
|
pVc->htCall = TapiBuffer->htCall;
|
|
|
|
pVc->CallInfo->ulLineDeviceID = TapiLine->CmLineID;
|
|
pVc->CallInfo->ulAddressID = TapiAddr->AddrId;
|
|
pVc->CallInfo->ulOrigin = LINECALLORIGIN_OUTBOUND;
|
|
|
|
//
|
|
// Set up intended bearer and media mode
|
|
//
|
|
pVc->CallInfo->ulBearerMode =
|
|
pTapiCallParams->ulBearerMode;
|
|
|
|
pVc->CallInfo->ulMediaMode =
|
|
pTapiCallParams->ulMediaMode;
|
|
|
|
if (pTapiCallParams->ulMaxRate == 0) {
|
|
|
|
pVc->CallInfo->ulRate =
|
|
TapiLine->DevCaps->ulMaxRate;
|
|
|
|
} else {
|
|
|
|
pVc->CallInfo->ulRate =
|
|
pTapiCallParams->ulMaxRate;
|
|
}
|
|
|
|
if (!InsertVcInTable(pVc)) {
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI,
|
|
("PxTapiMakeCall: failed to insert in vc table\n"));
|
|
|
|
PxFreeVc(pVc);
|
|
Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Our call handle is an index into the call table
|
|
//
|
|
TapiBuffer->hdCall = (HDRV_CALL)pVc->hdCall;
|
|
|
|
Status = NdisCoCreateVc(pAdapter->ClBindingHandle,
|
|
pClAf->NdisAfHandle,
|
|
(NDIS_HANDLE)pVc->hdCall,
|
|
&pVc->ClVcHandle);
|
|
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
RemoveVcFromTable(pVc);
|
|
PxFreeVc(pVc);
|
|
Status = NDIS_STATUS_TAPI_CALLUNAVAIL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Move (AF-specific) call parameters into NdisCallParams structure
|
|
//
|
|
Status =
|
|
(*pClAf->AfGetNdisCallParams)(pVc,
|
|
TapiLine->CmLineID,
|
|
TapiAddr->AddrId,
|
|
CO_TAPI_FLAG_OUTGOING_CALL,
|
|
TapiBuffer,
|
|
&pNdisCallParams);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI,
|
|
("PxTapiMakeCall: failed to move call params: Status %x\n", Status));
|
|
|
|
NdisCoDeleteVc(pVc->ClVcHandle);
|
|
RemoveVcFromTable(pVc);
|
|
PxFreeVc(pVc);
|
|
Status = NDIS_STATUS_TAPI_INVALCALLPARAMS;
|
|
break;
|
|
}
|
|
|
|
// Store Call Params for when lineGetID dispatches an incoming call...
|
|
//
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->pCallParameters = pNdisCallParams;
|
|
pVc->PrevState = pVc->State;
|
|
pVc->State = PX_VC_PROCEEDING;
|
|
pVc->Flags |= PX_VC_OWNER;
|
|
|
|
//
|
|
// Ref applied ndis part of the make call.
|
|
// This ref is removed in PxClCloseCallComplete or
|
|
// PxClMakeCallComplete in the case of a make call
|
|
// failure.
|
|
//
|
|
REF_VC(pVc);
|
|
|
|
//
|
|
// Indicate call state change to TAPI
|
|
//
|
|
SendTapiCallState(pVc,
|
|
LINECALLSTATE_PROCEEDING,
|
|
0,
|
|
pVc->CallInfo->ulMediaMode);
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
Status =
|
|
NdisClMakeCall(pVc->ClVcHandle,
|
|
pVc->pCallParameters,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
|
|
PxClMakeCallComplete(Status,
|
|
(NDIS_HANDLE)pVc->hdCall,
|
|
NULL,
|
|
pVc->pCallParameters);
|
|
}
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
} // end of do loop
|
|
|
|
while (FALSE);
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiMakeCall: exit Status %x\n", Status));
|
|
|
|
DEREF_TAPILINE(TapiLine);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetDevCaps(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Stick the appropriate device info into the request buffer.
|
|
|
|
Arguments:
|
|
|
|
Request -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PPX_TAPI_LINE TapiLine = NULL;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PNDIS_TAPI_GET_DEV_CAPS pNdisTapiGetDevCaps =
|
|
(PNDIS_TAPI_GET_DEV_CAPS) pNdisTapiRequest->Data;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevCaps: enter\n"));
|
|
|
|
if (!IsTapiDeviceValid(pNdisTapiGetDevCaps->ulDeviceID, &TapiLine)) {
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI,
|
|
( "PxTapiGetDevCaps: NDISTAPIERR_BADDEVICEID: line = %x\n",
|
|
pNdisTapiGetDevCaps->ulDeviceID));
|
|
return(NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
do {
|
|
|
|
ULONG SizeDevCaps;
|
|
ULONG DevClassesSize = 0;
|
|
USHORT DevClassesList[512];
|
|
WCHAR LineName[128];
|
|
ULONG LineNameSize;
|
|
WCHAR ProviderInfo[128];
|
|
ULONG ProviderInfoSize;
|
|
PLINE_DEV_CAPS ldc;
|
|
PPX_ADAPTER ClAdapter;
|
|
ULONG SizeToMove;
|
|
LONG SizeLeft;
|
|
PUCHAR dst;
|
|
ULONG TotalSize;
|
|
|
|
//
|
|
// Synchronously get dev caps for this device
|
|
//
|
|
|
|
ClAdapter = TapiLine->TapiProvider->Adapter;
|
|
|
|
ldc = TapiLine->DevCaps;
|
|
|
|
SizeDevCaps = ldc->ulUsedSize;
|
|
|
|
//
|
|
// Add some space for our providerinfo if needed
|
|
//
|
|
if (ldc->ulProviderInfoSize == 0) {
|
|
|
|
NdisZeroMemory(ProviderInfo, sizeof(ProviderInfo));
|
|
|
|
ProviderInfoSize = wcslen(L"NDPROXY") * sizeof(WCHAR);
|
|
|
|
NdisMoveMemory((PUCHAR)ProviderInfo,
|
|
L"NDPROXY",
|
|
ProviderInfoSize);
|
|
|
|
//
|
|
// For NULL termination
|
|
//
|
|
ProviderInfoSize += sizeof(UNICODE_NULL);
|
|
|
|
SizeDevCaps += ProviderInfoSize;
|
|
}
|
|
|
|
//
|
|
// Add some space for our linename if needed
|
|
//
|
|
if ((ldc->ulLineNameSize == 0) &&
|
|
(ClAdapter != NULL) &&
|
|
(ClAdapter->MediaNameLength != 0)) {
|
|
PUCHAR dst;
|
|
|
|
NdisZeroMemory(LineName, sizeof(LineName));
|
|
|
|
dst = (PUCHAR)LineName;
|
|
|
|
NdisMoveMemory(dst,
|
|
(PUCHAR)(ClAdapter->MediaName),
|
|
ClAdapter->MediaNameLength);
|
|
|
|
(ULONG_PTR)dst += ClAdapter->MediaNameLength;
|
|
|
|
//
|
|
// ToDo! Shoud get the name of the adapter
|
|
// and insert here!
|
|
//
|
|
|
|
NdisMoveMemory(dst,
|
|
L" - Line",
|
|
wcslen(L" - Line") * sizeof(WCHAR));
|
|
|
|
(ULONG_PTR)dst +=
|
|
wcslen(L" - Line") * sizeof(WCHAR);
|
|
|
|
(VOID)
|
|
IntegerToWChar(TapiLine->CmLineID,
|
|
-4,
|
|
(WCHAR *)dst);
|
|
|
|
(ULONG_PTR)dst += 4 * sizeof(WCHAR);
|
|
|
|
LineNameSize = (ULONG)((ULONG_PTR)dst - (ULONG_PTR)LineName);
|
|
|
|
//
|
|
// For NULL termination
|
|
//
|
|
LineNameSize += sizeof(UNICODE_NULL);
|
|
|
|
SizeDevCaps += LineNameSize;
|
|
}
|
|
|
|
//
|
|
// Add some space for our device classes
|
|
//
|
|
DevClassesSize = sizeof(DevClassesList);
|
|
NdisZeroMemory((PUCHAR)DevClassesList,
|
|
sizeof(DevClassesList));
|
|
|
|
if (ClAdapter != NULL) {
|
|
GetAllDevClasses(ClAdapter,
|
|
DevClassesList,
|
|
&DevClassesSize);
|
|
}
|
|
|
|
SizeDevCaps += DevClassesSize;
|
|
|
|
ldc = &pNdisTapiGetDevCaps->LineDevCaps;
|
|
|
|
SizeToMove = (TapiLine->DevCaps->ulUsedSize > ldc->ulTotalSize) ?
|
|
ldc->ulTotalSize : TapiLine->DevCaps->ulUsedSize;
|
|
|
|
SizeLeft = ldc->ulTotalSize - SizeToMove;
|
|
|
|
//
|
|
// Save the total size
|
|
//
|
|
TotalSize = ldc->ulTotalSize;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("PxTapiGetDevCaps: got device %x from ID %d: moving %d bytes\n",
|
|
TapiLine,
|
|
pNdisTapiGetDevCaps->ulDeviceID,
|
|
SizeToMove));
|
|
|
|
NdisMoveMemory((PUCHAR)ldc,
|
|
(PUCHAR)TapiLine->DevCaps,
|
|
SizeToMove);
|
|
|
|
ldc->ulNeededSize = SizeDevCaps;
|
|
ldc->ulTotalSize = TotalSize;
|
|
ldc->ulUsedSize = SizeToMove;
|
|
|
|
if (SizeLeft > 0) {
|
|
|
|
//
|
|
// If there is no provider info fill our proxy info
|
|
//
|
|
if (ldc->ulProviderInfoSize == 0) {
|
|
|
|
dst = (PUCHAR)ldc + ldc->ulUsedSize;
|
|
|
|
SizeToMove = (SizeLeft > (LONG)ProviderInfoSize) ?
|
|
ProviderInfoSize : SizeLeft;
|
|
|
|
NdisMoveMemory(dst,
|
|
(PUCHAR)ProviderInfo,
|
|
SizeToMove);
|
|
|
|
ldc->ulProviderInfoSize = SizeToMove;
|
|
ldc->ulProviderInfoOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
|
|
ldc->ulUsedSize += SizeToMove;
|
|
|
|
SizeLeft -= SizeToMove;
|
|
}
|
|
}
|
|
|
|
if (SizeLeft > 0) {
|
|
//
|
|
// If these is no line name fill in our line name
|
|
//
|
|
if (ldc->ulLineNameSize == 0 &&
|
|
ClAdapter != NULL &&
|
|
ClAdapter->MediaNameLength != 0) {
|
|
|
|
dst = (PUCHAR)ldc + ldc->ulUsedSize;
|
|
|
|
SizeToMove = (SizeLeft > (LONG)LineNameSize) ?
|
|
LineNameSize : SizeLeft;
|
|
|
|
NdisMoveMemory(dst,
|
|
(PUCHAR)LineName,
|
|
SizeToMove);
|
|
|
|
ldc->ulLineNameSize = SizeToMove;
|
|
ldc->ulLineNameOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
|
|
ldc->ulUsedSize += SizeToMove;
|
|
|
|
SizeLeft -= SizeToMove;
|
|
}
|
|
}
|
|
|
|
if (SizeLeft > 0) {
|
|
//
|
|
// Add the devclasses to the end
|
|
//
|
|
if (DevClassesSize > 0) {
|
|
|
|
dst = (PUCHAR)ldc + ldc->ulUsedSize;
|
|
|
|
SizeToMove = (SizeLeft > (LONG)DevClassesSize) ?
|
|
DevClassesSize : SizeLeft;
|
|
|
|
NdisMoveMemory(dst,
|
|
DevClassesList,
|
|
SizeToMove);
|
|
|
|
ldc->ulDeviceClassesSize = SizeToMove;
|
|
ldc->ulDeviceClassesOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
|
|
ldc->ulUsedSize += SizeToMove;
|
|
|
|
SizeLeft -= SizeToMove;
|
|
}
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
DEREF_TAPILINE_LOCKED(TapiLine);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevCaps: exit: used=%d, needed=%d, total=%d\n",
|
|
pNdisTapiGetDevCaps->LineDevCaps.ulUsedSize,
|
|
pNdisTapiGetDevCaps->LineDevCaps.ulNeededSize,
|
|
pNdisTapiGetDevCaps->LineDevCaps.ulTotalSize));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiAccept(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAccept: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAccept: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiAnswer(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_ANSWER pNdisTapiAnswer;
|
|
PPX_VC pVc = NULL;
|
|
NDIS_STATUS Status;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAnswer: enter\n"));
|
|
|
|
pNdisTapiAnswer =
|
|
(PNDIS_TAPI_ANSWER)pNdisTapiRequest->Data;
|
|
|
|
if (!IsVcValid(pNdisTapiAnswer->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiAnswer: pVc invalid call handle %d\n",
|
|
pNdisTapiAnswer->hdCall));
|
|
|
|
return(NDIS_STATUS_TAPI_INVALCALLHANDLE);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
do {
|
|
|
|
if (pVc->State != PX_VC_OFFERING) {
|
|
|
|
//
|
|
// call in wrong state
|
|
//
|
|
PXDEBUGP(PXD_FATAL, PXM_TAPI, ("PxTapiAnswer: pVc VC %x/%x invalid state %x\n",
|
|
pVc, pVc->Flags,
|
|
pVc->ulCallState));
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
Status = NDIS_STATUS_TAPI_INVALCALLSTATE;
|
|
|
|
break;
|
|
}
|
|
|
|
if (pVc->Flags & PX_VC_CALLTIMER_STARTED) {
|
|
PxStopIncomingCallTimeout(pVc);
|
|
}
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiAnswer: calling NdisClIncomingCallComplete\n"));
|
|
|
|
pVc->PrevState = pVc->State;
|
|
pVc->State = PX_VC_CONNECTED;
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
NdisClIncomingCallComplete (NDIS_STATUS_SUCCESS,
|
|
pVc->ClVcHandle,
|
|
pVc->pCallParameters);
|
|
} while (FALSE);
|
|
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC(pVc);
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiAnswer: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiLineGetID(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a handle to the client wich is returned to the tapi application.
|
|
This handle is only meaning full to the client and will vary depending
|
|
on the deviceclass.
|
|
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_ID pNdisTapiGetId =
|
|
(PNDIS_TAPI_GET_ID)pNdisTapiRequest->Data;
|
|
|
|
PVAR_STRING DeviceID = &pNdisTapiGetId->DeviceID;
|
|
PPX_VC pVc = NULL;
|
|
NDIS_HANDLE VcHandle = NULL;
|
|
PPX_CM_AF pCmAf;
|
|
PPX_CM_SAP pCmSap;
|
|
NDIS_STATUS Status;
|
|
LPCWSTR DevClass;
|
|
ULONG DevClassSize;
|
|
PPX_ADAPTER pAdapter;
|
|
|
|
DevClass =
|
|
(LPCWSTR)(((CHAR *)pNdisTapiGetId) + pNdisTapiGetId->ulDeviceClassOffset);
|
|
|
|
DevClassSize = pNdisTapiGetId->ulDeviceClassSize;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiLineGetID: enter. CallId %x, DevClass = %ls\n", pNdisTapiGetId->hdCall, DevClass));
|
|
|
|
if (pNdisTapiGetId->ulSelect != LINECALLSELECT_CALL) {
|
|
return (NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
//
|
|
// validate call handle and get call pointer
|
|
//
|
|
if (!IsVcValid(pNdisTapiGetId->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxNdisTapiGetId: pVc invalid call handle %d\n",
|
|
pNdisTapiGetId->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
do {
|
|
//
|
|
// ToDo!
|
|
//
|
|
// If we already are working with a client
|
|
// we need to see if this is a mapping to the same
|
|
// client or to a different one. If it is to the
|
|
// same one just return the current handle. If it
|
|
// is to a different one we should either fail or
|
|
// tear the vc hand-off down from the current client
|
|
// and then hand-off to the new client.
|
|
//
|
|
if (pVc->CmVcHandle != NULL) {
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
|
|
if (pVc->State != PX_VC_CONNECTED) {
|
|
Status = NDIS_STATUS_TAPI_INVALCALLSTATE;
|
|
break;
|
|
}
|
|
|
|
pAdapter = pVc->Adapter;
|
|
|
|
//
|
|
// Find the sap/af of the client that we need to indicate this on
|
|
//
|
|
if (!PxAfAndSapFromDevClass(pAdapter,
|
|
DevClass,
|
|
&pCmAf,
|
|
&pCmSap)) {
|
|
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiLineGetID: SAP not found!\n"));
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
|
|
break;
|
|
}
|
|
|
|
pVc->HandoffState = PX_VC_HANDOFF_OFFERING;
|
|
pVc->CmAf = pCmAf;
|
|
pVc->CmSap = pCmSap;
|
|
|
|
VcHandle = pVc->ClVcHandle;
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
//
|
|
// Create the Vc
|
|
//
|
|
Status = NdisCoCreateVc(pAdapter->CmBindingHandle,
|
|
pCmAf->NdisAfHandle,
|
|
(NDIS_HANDLE)pVc->hdCall,
|
|
&VcHandle);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiLineGetID: Client refused Vc CmAf %p DevClass %ls Status %x\n",
|
|
pCmAf, DevClass, Status));
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
|
|
//
|
|
// remove ref that was applied when we mapped the devclass
|
|
// to an af/sap.
|
|
//
|
|
DEREF_CM_AF(pCmAf);
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->HandoffState = PX_VC_HANDOFF_IDLE;
|
|
|
|
break;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->CmVcHandle = VcHandle;
|
|
|
|
//
|
|
// Apply a reference on the vc for
|
|
// activating this call with the client.
|
|
// This ref is removed in PxCmCloseCall.
|
|
//
|
|
REF_VC(pVc);
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
//
|
|
// Dispatch the incoming call to the client
|
|
//
|
|
Status =
|
|
NdisCmDispatchIncomingCall(pCmSap->NdisSapHandle,
|
|
pVc->CmVcHandle,
|
|
pVc->pCallParameters);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
Status = PxBlock(&pVc->Block);
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
//
|
|
// The client did not except the call
|
|
// delete the vc and go away.
|
|
//
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiLineGetID: Client rejected call VC %p, Status %x\n",
|
|
pVc, Status));
|
|
|
|
#ifdef CODELETEVC_FIXED
|
|
//
|
|
// Evidently the CoCreateVc is unbalanced
|
|
// when creating a proxy vc. The call to
|
|
// NdisCoDeleteVc will fail because the
|
|
// Vc is still active.
|
|
// ToDo! Investigate this with ndis
|
|
//
|
|
Status =
|
|
NdisCoDeleteVc(pVc->CmVcHandle);
|
|
|
|
#endif
|
|
//
|
|
// remove ref that was applied when we mapped the devclass
|
|
// to an af/sap.
|
|
//
|
|
DEREF_CM_AF(pCmAf);
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
#ifdef CODELETEVC_FIXED
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
pVc->CmVcHandle = NULL;
|
|
}
|
|
#endif
|
|
|
|
pVc->HandoffState = PX_VC_HANDOFF_IDLE;
|
|
|
|
//
|
|
// Remove the reference we applied before
|
|
// dispatching incoming call to client.
|
|
// We do not need to do all of the deref code
|
|
// because of the ref applied at entry to
|
|
// this function
|
|
//
|
|
pVc->RefCount--;
|
|
|
|
break;
|
|
}
|
|
|
|
NdisCmDispatchCallConnected(pVc->CmVcHandle);
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
//
|
|
// If we are still in the offering state
|
|
// we can safely move to connected at this
|
|
// point. We might not be in offering if
|
|
// right after we connected the client
|
|
// did an NdisClCloseCall before we could
|
|
// reacquire the spinlock.
|
|
//
|
|
if (pVc->HandoffState == PX_VC_HANDOFF_OFFERING) {
|
|
pVc->HandoffState = PX_VC_HANDOFF_CONNECTED;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
//
|
|
// If we get here and we are not in the connected
|
|
// state something happened to tear our call
|
|
// down with the client. This could have been
|
|
// an error attempting to create the call with the
|
|
// client or we received either a
|
|
// tapidrop from tapi
|
|
// incomingclosecall from cm
|
|
//
|
|
if (pVc->State != PX_VC_CONNECTED) {
|
|
|
|
Status =
|
|
PxCloseCallWithCl(pVc);
|
|
|
|
if ((Status != NDIS_STATUS_PENDING) &&
|
|
(pVc->Flags & PX_VC_CLEANUP_CM)) {
|
|
PxCloseCallWithCm(pVc);
|
|
}
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
|
|
} else if (Status == NDIS_STATUS_SUCCESS) {
|
|
|
|
Status = NdisCoGetTapiCallId(pVc->CmVcHandle,
|
|
DeviceID);
|
|
//
|
|
// ToDo?: If status is failure here, do we need to do anything? In our
|
|
// case this should be OK, because the TSP ensures the size of
|
|
// the VAR_STRING is right, and that's the only thing that can
|
|
// cause a failure.
|
|
//
|
|
}
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI,
|
|
("PxTapiLineGetID: Vc %p, Status %x\n", pVc, Status));
|
|
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiClose (
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI is closing it's handle to our device. We shouldn't see any further requests or
|
|
send any TAPI events after completing this function.
|
|
|
|
In the current design, we are the sole owner of all VCs (i.e. there are no 'pass-through' or monitor-only
|
|
functions in the Proxy). TAPI should not call this func before all calls have been closed and all apps
|
|
have disconnected.
|
|
|
|
NOTE: this function is also called by TAPI after we send it a LINE_REMOVE message, indicating that
|
|
the adapter has been unbound. In this case, too, we should already have closed all calls/freed VCs and
|
|
associated structures.
|
|
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_CLOSE pTapiClose =
|
|
(PNDIS_TAPI_CLOSE)pNdisTapiRequest->Data;
|
|
|
|
PPX_TAPI_LINE TapiLine;
|
|
PPX_VC pVc;
|
|
PPX_TAPI_PROVIDER TapiProvider;
|
|
PPX_CL_SAP pClSap;
|
|
PPX_CL_AF pClAf;
|
|
NDIS_STATUS Status;
|
|
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("PxTapiClose: ID: %d\n", pTapiClose->hdLine));
|
|
|
|
//
|
|
// validate line handle and get line pointer
|
|
//
|
|
if (!IsTapiLineValid((ULONG)pTapiClose->hdLine, &TapiLine)) {
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiClose: NDISTAPIERR_BADDEVICEID: line = %x\n", pTapiClose->hdLine));
|
|
return (NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
TapiLine->DevStatus->ulNumOpens--;
|
|
|
|
if (TapiLine->DevStatus->ulNumOpens != 0) {
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
pClAf = TapiLine->ClAf;
|
|
pClSap = TapiLine->ClSap;
|
|
TapiLine->ClSap = NULL;
|
|
|
|
TapiLine->DevStatus->ulOpenMediaModes = 0;
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
|
|
//
|
|
// If we have any active Vc's on this line we need
|
|
// tear them down.
|
|
//
|
|
if (pClAf != NULL) {
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
|
|
REF_CL_AF(pClAf);
|
|
|
|
#if 0
|
|
while (!IsListEmpty(&pClAf->VcList)) {
|
|
PLIST_ENTRY Entry;
|
|
PPX_VC pActiveVc;
|
|
|
|
Entry = RemoveHeadList(&pClAf->VcList);
|
|
|
|
InsertHeadList(&pClAf->VcClosingList, Entry);
|
|
|
|
pActiveVc =
|
|
CONTAINING_RECORD(Entry, PX_VC, ClAfLinkage);
|
|
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
|
|
NdisAcquireSpinLock(&pActiveVc->Lock);
|
|
|
|
if (!(pActiveVc->CloseFlags & PX_VC_TAPI_CLOSE)) {
|
|
|
|
REF_VC(pActiveVc);
|
|
|
|
pActiveVc->CloseFlags |= PX_VC_TAPI_CLOSE;
|
|
|
|
PxVcCleanup(pActiveVc, 0);
|
|
|
|
PxTapiCompleteAllIrps(pActiveVc, NDIS_STATUS_SUCCESS);
|
|
|
|
//
|
|
// Remove the ref applied in the make call or call offering
|
|
// indication. We do not need the full deref code because
|
|
// of the ref applied at entry.
|
|
//
|
|
pActiveVc->RefCount--;
|
|
|
|
DEREF_VC_LOCKED(pActiveVc);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
}
|
|
#endif
|
|
//
|
|
// If we have a sap registered on this line we need
|
|
// to close it.
|
|
//
|
|
if (pClSap != NULL) {
|
|
|
|
// If the SAP is opened then we need to close it
|
|
if (pClSap->State == PX_SAP_OPENED) {
|
|
|
|
RemoveEntryList(&pClSap->Linkage);
|
|
|
|
InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
|
|
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
|
|
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
|
|
|
|
Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
PxClDeregisterSapComplete(Status, pClSap);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
}
|
|
|
|
}
|
|
|
|
DEREF_CL_AF_LOCKED(pClAf);
|
|
}
|
|
|
|
DEREF_TAPILINE(TapiLine);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiCloseCall(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall =
|
|
(PNDIS_TAPI_CLOSE_CALL)pNdisTapiRequest->Data;
|
|
|
|
PPX_VC pVc;
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
|
|
if (!IsVcValid(pNdisTapiCloseCall->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiCloseCall: invalid call handle %d\n",
|
|
pNdisTapiCloseCall->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI,
|
|
("PxTapiCloseCall: enter. VC = %x, State = %x\n",
|
|
pVc, pVc->State));
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->CloseFlags |= PX_VC_TAPI_CLOSECALL;
|
|
|
|
//
|
|
// Check the Vc state and act accordingly
|
|
//
|
|
PxVcCleanup(pVc, 0);
|
|
|
|
PxTapiCompleteAllIrps(pVc, NDIS_STATUS_SUCCESS);
|
|
|
|
//
|
|
// Remove the ref applied in the make call or call offering
|
|
// indication. We do not need the full deref code because
|
|
// of the ref applied at entry.
|
|
//
|
|
pVc->RefCount--;
|
|
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiCloseCall: exit.\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
PxTapiConditionalMediaDetection(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConditionalMediaDetection: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConditionalMediaDetection: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiConfigDialog (
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConfigDialog: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConfigDialog: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiDevSpecific(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
D for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDevSpecific: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDevSpecific: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiDial(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDial: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDial: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiDrop(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Drop the call without deallocating the VC.
|
|
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PPX_VC pVc;
|
|
PIRP Irp;
|
|
|
|
PNDIS_TAPI_DROP pNdisTapiDrop =
|
|
(PNDIS_TAPI_DROP)pNdisTapiRequest->Data;
|
|
|
|
if (!IsVcValid(pNdisTapiDrop->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiDrop: invalid call handle %d\n",
|
|
pNdisTapiDrop->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("PxTapiDrop enter: Vc: %p VcState: %x CallState: %x\n", pVc, pVc->State, pVc->ulCallState ));
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
Irp = pNdisTapiRequest->Irp;
|
|
|
|
IoSetCancelRoutine(Irp, PxCancelSetQuery);
|
|
|
|
//
|
|
// Insert the request in the Vc's pending list
|
|
//
|
|
InsertTailList(&pVc->PendingDropReqs,
|
|
&pNdisTapiRequest->Linkage);
|
|
|
|
pVc->CloseFlags |= PX_VC_TAPI_DROP;
|
|
|
|
//
|
|
// Check the Vc state and act accordingly
|
|
//
|
|
Status =
|
|
PxVcCleanup(pVc, PX_VC_DROP_PENDING);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
RemoveEntryList(&pNdisTapiRequest->Linkage);
|
|
IoSetCancelRoutine(Irp, NULL);
|
|
}
|
|
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetAddressCaps(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps =
|
|
(PNDIS_TAPI_GET_ADDRESS_CAPS) pNdisTapiRequest->Data;
|
|
PPX_TAPI_LINE TapiLine;
|
|
PPX_TAPI_ADDR TapiAddr;
|
|
PPX_ADAPTER ClAdapter;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
if (!IsTapiDeviceValid(pNdisTapiRequest->ulDeviceID, &TapiLine)) {
|
|
PXDEBUGP (PXD_WARNING, PXM_TAPI, ( "PxTapiGetAddressCaps: NDISTAPIERR_BADDEVICEID: line = %x\n", pNdisTapiRequest->ulDeviceID));
|
|
return (NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("PxTapiGetAddressCaps: got device %p from ID %d\n",
|
|
TapiLine, pNdisTapiRequest->ulDeviceID));
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
do {
|
|
ULONG DevClassesSize = 0;
|
|
USHORT DevClassesList[512];
|
|
ULONG SizeToMove;
|
|
ULONG TotalSize;
|
|
ULONG SizeLeft;
|
|
PLINE_ADDRESS_CAPS In, Out;
|
|
|
|
|
|
//
|
|
// Get the tapi address that we are interested in
|
|
//
|
|
if (!IsAddressValid(TapiLine,
|
|
pNdisTapiGetAddressCaps->ulAddressID,
|
|
&TapiAddr)) {
|
|
|
|
Status = NDIS_STATUS_TAPI_INVALADDRESSID;
|
|
break;
|
|
}
|
|
|
|
In = TapiAddr->Caps;
|
|
Out = &pNdisTapiGetAddressCaps->LineAddressCaps;
|
|
|
|
//
|
|
// Add some space for our device classes
|
|
//
|
|
DevClassesSize = sizeof(DevClassesList);
|
|
NdisZeroMemory((PUCHAR)DevClassesList,
|
|
sizeof(DevClassesList));
|
|
|
|
if (TapiLine->TapiProvider->Adapter != NULL) {
|
|
GetAllDevClasses(TapiLine->TapiProvider->Adapter,
|
|
DevClassesList,
|
|
&DevClassesSize);
|
|
}
|
|
|
|
//
|
|
// Synchronously get Address caps for this device
|
|
//
|
|
SizeToMove = (In->ulUsedSize > Out->ulTotalSize) ?
|
|
Out->ulTotalSize : In->ulUsedSize;
|
|
|
|
TotalSize = Out->ulTotalSize;
|
|
|
|
NdisMoveMemory((PUCHAR)Out, (PUCHAR)In, SizeToMove);
|
|
|
|
SizeLeft =
|
|
TotalSize - SizeToMove;
|
|
|
|
Out->ulTotalSize = TotalSize;
|
|
Out->ulUsedSize = SizeToMove;
|
|
Out->ulNeededSize =
|
|
In->ulUsedSize + DevClassesSize;
|
|
|
|
if (SizeLeft > 0) {
|
|
//
|
|
// If these is room fill in our devclasses
|
|
//
|
|
if (DevClassesSize > 0) {
|
|
PUCHAR dst;
|
|
|
|
dst = (PUCHAR)Out + Out->ulUsedSize;
|
|
|
|
SizeToMove = (SizeLeft > DevClassesSize) ?
|
|
DevClassesSize : SizeLeft;
|
|
|
|
NdisMoveMemory(dst, DevClassesList, SizeToMove);
|
|
Out->ulDeviceClassesSize = SizeToMove;
|
|
Out->ulDeviceClassesOffset =
|
|
(ULONG)((ULONG_PTR)dst - (ULONG_PTR)Out);
|
|
Out->ulUsedSize += SizeToMove;
|
|
SizeLeft -= SizeToMove;
|
|
}
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
DEREF_TAPILINE_LOCKED(TapiLine);
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetAddressCaps: exit. \n"));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetAddressID(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_ADDRESS_ID TapiBuffer =
|
|
(PNDIS_TAPI_GET_ADDRESS_ID) pNdisTapiRequest->Data;
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: enter\n"));
|
|
|
|
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetAddressID: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
|
|
return(NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
//
|
|
// ToDo!
|
|
//
|
|
TapiBuffer->ulAddressID = 0;
|
|
|
|
DEREF_TAPILINE_LOCKED(TapiLine);
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetAddressStatus(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Placeholder for TAPI OID action routines
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: enter\n"));
|
|
|
|
//
|
|
// ToDo!
|
|
//
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetCallAddressID(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_CALL_ADDRESS_ID TapiBuffer =
|
|
(PNDIS_TAPI_GET_CALL_ADDRESS_ID)pNdisTapiRequest->Data;
|
|
|
|
PPX_VC pVc;
|
|
|
|
if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallAddressID: invalid call handle %d\n",
|
|
TapiBuffer->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: Vc: %p\n", pVc));
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
TapiBuffer->ulAddressID = pVc->TapiAddr->AddrId;
|
|
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetCallInfo(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_CALL_INFO TapiBuffer =
|
|
(PNDIS_TAPI_GET_CALL_INFO)pNdisTapiRequest->Data;
|
|
|
|
PPX_VC pVc;
|
|
PPX_TAPI_LINE TapiLine;
|
|
LINE_CALL_INFO* CallInfo;
|
|
LINE_CALL_INFO* OutCallInfo = &TapiBuffer->LineCallInfo;
|
|
ULONG VarDataSize = 0; // Total available
|
|
ULONG VarDataUsed = 0;
|
|
|
|
if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallInfo: invalid call handle %d\n",
|
|
TapiBuffer->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
//
|
|
// Make sure we have enough space to copy everything over
|
|
//
|
|
CallInfo = pVc->CallInfo;
|
|
TapiLine = pVc->TapiLine;
|
|
|
|
VarDataSize =
|
|
pNdisTapiRequest->ulDataSize - sizeof(NDIS_TAPI_GET_CALL_INFO);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI,
|
|
("PxTapiGetCallInfo: enter. pVc = %p, AvailSize = %x, needed = %x\n",
|
|
pVc, OutCallInfo->ulTotalSize, CallInfo->ulUsedSize));
|
|
|
|
OutCallInfo->ulNeededSize = CallInfo->ulUsedSize;
|
|
|
|
//
|
|
// Patch up the Id here. We store it in our callinfo
|
|
// block in terms of the call managers 0 based Id. We
|
|
// need to give tapi the Id it is looking for which is
|
|
// stored in the tapiline.
|
|
//
|
|
OutCallInfo->ulLineDeviceID = TapiLine->ulDeviceID;
|
|
|
|
OutCallInfo->ulAddressID = CallInfo->ulAddressID;
|
|
|
|
OutCallInfo->ulBearerMode = CallInfo->ulBearerMode;
|
|
|
|
OutCallInfo->ulRate = CallInfo->ulRate;
|
|
|
|
OutCallInfo->ulMediaMode = CallInfo->ulMediaMode;
|
|
|
|
OutCallInfo->ulAppSpecific = CallInfo->ulAppSpecific;
|
|
OutCallInfo->ulCallID = 0;
|
|
OutCallInfo->ulRelatedCallID = 0;
|
|
OutCallInfo->ulCallParamFlags = 0;
|
|
|
|
OutCallInfo->DialParams.ulDialPause = 0;
|
|
OutCallInfo->DialParams.ulDialSpeed = 0;
|
|
OutCallInfo->DialParams.ulDigitDuration = 0;
|
|
OutCallInfo->DialParams.ulWaitForDialtone = 0;
|
|
|
|
OutCallInfo->ulReason = CallInfo->ulReason;
|
|
OutCallInfo->ulCompletionID = 0;
|
|
|
|
OutCallInfo->ulCountryCode = 0;
|
|
OutCallInfo->ulTrunk = (ULONG)-1;
|
|
|
|
//
|
|
// Do the CallerID
|
|
//
|
|
if (CallInfo->ulCallerIDSize) {
|
|
|
|
if (((VarDataUsed + CallInfo->ulCallerIDSize) <= VarDataSize) &&
|
|
((CallInfo->ulCallerIDOffset + CallInfo->ulCallerIDSize) <= CallInfo->ulUsedSize)) {
|
|
|
|
OutCallInfo->ulCallerIDSize = CallInfo->ulCallerIDSize;
|
|
OutCallInfo->ulCallerIDFlags = CallInfo->ulCallerIDFlags;
|
|
OutCallInfo->ulCallerIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
|
|
NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCallerIDOffset,
|
|
(PUCHAR)(CallInfo)+CallInfo->ulCallerIDOffset,
|
|
CallInfo->ulCallerIDSize);
|
|
|
|
VarDataUsed += CallInfo->ulCallerIDSize;
|
|
pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLERID;
|
|
}
|
|
} else {
|
|
|
|
OutCallInfo->ulCallerIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
OutCallInfo->ulCallerIDSize = 0;
|
|
OutCallInfo->ulCallerIDOffset = 0;
|
|
}
|
|
|
|
OutCallInfo->ulCallerIDNameSize = 0;
|
|
OutCallInfo->ulCallerIDNameOffset = 0;
|
|
|
|
//
|
|
// Do the CalledID
|
|
//
|
|
if (CallInfo->ulCalledIDSize) {
|
|
if (((VarDataUsed + CallInfo->ulCalledIDSize) <= VarDataSize) &&
|
|
((CallInfo->ulCalledIDOffset + CallInfo->ulCalledIDSize) <= CallInfo->ulUsedSize)) {
|
|
|
|
OutCallInfo->ulCalledIDFlags = CallInfo->ulCalledIDFlags;
|
|
OutCallInfo->ulCalledIDSize = CallInfo->ulCalledIDSize;
|
|
OutCallInfo->ulCalledIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
|
|
|
|
NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCalledIDOffset,
|
|
(PUCHAR)(CallInfo)+CallInfo->ulCalledIDOffset,
|
|
CallInfo->ulCalledIDSize);
|
|
|
|
VarDataUsed += CallInfo->ulCalledIDSize;
|
|
pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLEDID;
|
|
}
|
|
|
|
} else {
|
|
OutCallInfo->ulCalledIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
OutCallInfo->ulCalledIDSize = 0;
|
|
OutCallInfo->ulCalledIDOffset = 0;
|
|
}
|
|
|
|
OutCallInfo->ulCalledIDNameSize = 0;
|
|
OutCallInfo->ulCalledIDNameOffset = 0;
|
|
|
|
OutCallInfo->ulCallStates = LINECALLSTATE_IDLE |
|
|
LINECALLSTATE_OFFERING |
|
|
LINECALLSTATE_CONNECTED |
|
|
LINECALLSTATE_PROCEEDING |
|
|
LINECALLSTATE_DISCONNECTED |
|
|
LINECALLSTATE_SPECIALINFO |
|
|
LINECALLSTATE_UNKNOWN;
|
|
|
|
OutCallInfo->ulOrigin = (pVc->Flags & PX_VC_OWNER) ? LINECALLORIGIN_EXTERNAL : LINECALLORIGIN_OUTBOUND;
|
|
OutCallInfo->ulReason = LINECALLREASON_UNAVAIL;
|
|
OutCallInfo->ulCompletionID = 0;
|
|
OutCallInfo->ulConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
OutCallInfo->ulConnectedIDSize = 0;
|
|
OutCallInfo->ulConnectedIDOffset = 0;
|
|
OutCallInfo->ulConnectedIDNameSize = 0;
|
|
OutCallInfo->ulConnectedIDNameOffset = 0;
|
|
|
|
OutCallInfo->ulRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
OutCallInfo->ulRedirectionIDSize = 0;
|
|
OutCallInfo->ulRedirectionIDOffset = 0;
|
|
OutCallInfo->ulRedirectionIDNameSize = 0;
|
|
OutCallInfo->ulRedirectionIDNameOffset = 0;
|
|
|
|
OutCallInfo->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
OutCallInfo->ulRedirectingIDSize = 0;
|
|
OutCallInfo->ulRedirectingIDOffset = 0;
|
|
OutCallInfo->ulRedirectingIDNameSize = 0;
|
|
OutCallInfo->ulRedirectingIDNameOffset = 0;
|
|
|
|
OutCallInfo->ulDisplaySize = 0;
|
|
OutCallInfo->ulDisplayOffset = 0;
|
|
|
|
OutCallInfo->ulUserUserInfoSize = 0;
|
|
OutCallInfo->ulUserUserInfoOffset = 0;
|
|
|
|
OutCallInfo->ulHighLevelCompSize = 0;
|
|
OutCallInfo->ulHighLevelCompOffset = 0;
|
|
|
|
OutCallInfo->ulLowLevelCompSize = 0;
|
|
OutCallInfo->ulLowLevelCompOffset = 0;
|
|
|
|
OutCallInfo->ulChargingInfoSize = 0;
|
|
OutCallInfo->ulChargingInfoOffset = 0;
|
|
|
|
OutCallInfo->ulTerminalModesSize = 0;
|
|
OutCallInfo->ulTerminalModesOffset = 0;
|
|
|
|
OutCallInfo->ulDevSpecificSize = 0;
|
|
OutCallInfo->ulDevSpecificOffset = 0;
|
|
|
|
OutCallInfo->ulNeededSize =
|
|
OutCallInfo->ulUsedSize = sizeof(LINE_CALL_INFO) + VarDataUsed;
|
|
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetCallStatus (
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_CALL_STATUS TapiBuffer =
|
|
(PNDIS_TAPI_GET_CALL_STATUS)pNdisTapiRequest->Data;
|
|
|
|
PPX_VC pVc;
|
|
LINE_CALL_INFO* CallInfo;
|
|
LINE_CALL_STATUS* CallStatus = &TapiBuffer->LineCallStatus;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallStatus: enter\n"));\
|
|
|
|
if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallStatus: invalid call handle %d\n",
|
|
TapiBuffer->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
CallInfo = pVc->CallInfo;
|
|
|
|
CallStatus->ulUsedSize = sizeof(LINE_CALL_STATUS);
|
|
|
|
CallStatus->ulCallState = pVc->ulCallState;
|
|
|
|
//
|
|
// fill the mode depending on the call state
|
|
//
|
|
switch (pVc->ulCallState) {
|
|
case LINECALLSTATE_IDLE:
|
|
default:
|
|
CallStatus->ulCallStateMode = 0;
|
|
CallStatus->ulCallFeatures = 0;
|
|
break;
|
|
|
|
case LINECALLSTATE_CONNECTED:
|
|
CallStatus->ulCallStateMode = 0;
|
|
CallStatus->ulCallFeatures = LINECALLFEATURE_DROP;
|
|
break;
|
|
|
|
case LINECALLSTATE_OFFERING:
|
|
CallStatus->ulCallStateMode = 0;
|
|
CallStatus->ulCallFeatures = LINECALLFEATURE_ANSWER;
|
|
break;
|
|
|
|
case LINECALLSTATE_DISCONNECTED:
|
|
if (pVc->ulCallStateMode == 0x11 )
|
|
CallStatus->ulCallStateMode = LINEDISCONNECTMODE_BUSY;
|
|
else
|
|
CallStatus->ulCallStateMode = LINEDISCONNECTMODE_NOANSWER;
|
|
break;
|
|
|
|
case LINECALLSTATE_BUSY:
|
|
CallStatus->ulCallStateMode = LINEBUSYMODE_UNAVAIL;
|
|
break;
|
|
|
|
case LINECALLSTATE_SPECIALINFO:
|
|
// if(cm->NoActiveLine)
|
|
// CallStatus->ulCallStateMode = LINESPECIALINFO_NOCIRCUIT;
|
|
CallStatus->ulCallStateMode = 0;
|
|
break;
|
|
}
|
|
|
|
CallStatus->ulDevSpecificSize = 0;
|
|
CallStatus->ulDevSpecificOffset = 0;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("GetCallStatus: VC %x/%x, CallSt %x, Mode %x, Features %x\n",
|
|
pVc, pVc->Flags,
|
|
CallStatus->ulCallState,
|
|
CallStatus->ulCallStateMode,
|
|
CallStatus->ulCallFeatures));
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetDevConfig(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetExtensionID(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_EXTENSION_ID TapiBuffer = (PNDIS_TAPI_GET_EXTENSION_ID)pNdisTapiRequest->Data;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: enter\n"));
|
|
|
|
// TapiBuffer->LineExtensionID.ulExtensionID0 = 0;
|
|
// TapiBuffer->LineExtensionID.ulExtensionID1 = 0;
|
|
// TapiBuffer->LineExtensionID.ulExtensionID2 = 0;
|
|
// TapiBuffer->LineExtensionID.ulExtensionID3 = 0;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiGetLineDevStatus(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_GET_LINE_DEV_STATUS TapiBuffer =
|
|
(PNDIS_TAPI_GET_LINE_DEV_STATUS)pNdisTapiRequest->Data;
|
|
|
|
PPX_TAPI_LINE TapiLine;
|
|
PX_ADAPTER *pAdapter;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: enter\n"));
|
|
|
|
//
|
|
// validate line handle and get line pointer
|
|
//
|
|
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
|
|
return (NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: got device %p from ID %d\n", TapiLine, TapiBuffer->hdLine));
|
|
|
|
//
|
|
// Get MediaModes and Current Calls
|
|
//
|
|
TapiBuffer->LineDevStatus.ulOpenMediaModes =
|
|
TapiLine->DevStatus->ulOpenMediaModes;
|
|
|
|
TapiBuffer->LineDevStatus.ulNumActiveCalls =
|
|
TapiLine->DevStatus->ulNumActiveCalls;
|
|
|
|
TapiBuffer->LineDevStatus.ulDevStatusFlags =
|
|
TapiLine->DevStatus->ulDevStatusFlags;
|
|
|
|
DEREF_TAPILINE_LOCKED(TapiLine);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiNegotiateExtVersion(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion =
|
|
(PNDIS_TAPI_NEGOTIATE_EXT_VERSION) pNdisTapiRequest->Data;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: enter\n"));
|
|
|
|
pNdisTapiNegotiateExtVersion->ulExtVersion = 0;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: exit NDIS_STATUS_TAPI_OPERATIONUNAVAIL\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSendUserUserInfo(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: enter\n"));
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSetAppSpecific(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific =
|
|
(PNDIS_TAPI_SET_APP_SPECIFIC)(pNdisTapiRequest->Data);
|
|
|
|
PPX_VC pVc;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: enter\n"));
|
|
|
|
if (!IsVcValid(pNdisTapiSetAppSpecific->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetAppSpecific: pVc invalid call handle %d\n",
|
|
pNdisTapiSetAppSpecific->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
//
|
|
// Get the VC, and re-set the app specific longword.
|
|
//
|
|
pVc->CallInfo->ulAppSpecific =
|
|
pNdisTapiSetAppSpecific->ulAppSpecific;
|
|
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSetCallParams(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: enter\n"));
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSetDefaultMediaDetection(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION TapiBuffer =
|
|
(PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)pNdisTapiRequest->Data;
|
|
PPX_CL_AF pClAf = NULL;
|
|
PPX_CL_SAP pClSap = NULL;
|
|
PCO_SAP pCoSap;
|
|
PPX_TAPI_LINE TapiLine = NULL;
|
|
NDIS_STATUS Status;
|
|
BOOLEAN Found = FALSE;
|
|
PPX_TAPI_PROVIDER TapiProvider;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: enter\n"));
|
|
|
|
//
|
|
// validate line handle and get line pointer
|
|
//
|
|
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiSetDefaultMediaDetection: NDISTAPIERR_BADDEVICEID: line = %x\n",
|
|
TapiBuffer->hdLine));
|
|
return (NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI,
|
|
("PxTapiSetDefaultMediaDetection: got TapiLine %p from ID %d\n",
|
|
TapiLine, TapiBuffer->hdLine));
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
do {
|
|
|
|
//
|
|
// Is this line in service? (does it have an valid af?)
|
|
//
|
|
if (!(TapiLine->DevStatus->ulDevStatusFlags &
|
|
LINEDEVSTATUSFLAGS_INSERVICE)) {
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiSetDefaultMediaDetection: Line not in service!\n"));
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
Status = NDIS_STATUS_TAPI_INVALLINESTATE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make sure this line supports these media modes
|
|
//
|
|
if ((TapiBuffer->ulMediaModes & TapiLine->DevCaps->ulMediaModes) !=
|
|
TapiBuffer->ulMediaModes) {
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiSetDefaultMediaDetection: invalid media mode\n"));
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// See if we already have these media modes open
|
|
//
|
|
if ((TapiBuffer->ulMediaModes &
|
|
~TapiLine->DevStatus->ulOpenMediaModes) == 0) {
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiSetDefaultMediaDetection: Already have a sap!\n"));
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
TapiLine->DevStatus->ulOpenMediaModes |=
|
|
TapiBuffer->ulMediaModes;
|
|
|
|
pClAf = TapiLine->ClAf;
|
|
|
|
pClSap = TapiLine->ClSap;
|
|
TapiLine->ClSap = NULL;
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiSetDefaultMediaDetection: TapiLine: %p, pClAf: %p, MediaModes: %x\n",
|
|
TapiLine, pClAf, TapiLine->DevStatus->ulOpenMediaModes));
|
|
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
|
|
REF_CL_AF(pClAf);
|
|
|
|
if (pClSap != NULL) {
|
|
//
|
|
// We already have a sap on this line. We only need one
|
|
// per line so let's deregister the old one before registering
|
|
// the new one.
|
|
//
|
|
RemoveEntryList(&pClSap->Linkage);
|
|
|
|
InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
|
|
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
|
|
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
|
|
|
|
Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
PxClDeregisterSapComplete(Status, pClSap);
|
|
}
|
|
|
|
} else {
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
}
|
|
|
|
//
|
|
// Get a SAP translation for this Media Mode setting.
|
|
// The function is called with the Af lock held and
|
|
// returns with the Af lock released!
|
|
//
|
|
pClSap = (*pClAf->AfGetNdisSap)(pClAf, TapiLine);
|
|
|
|
if (pClSap == NULL) {
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
|
|
InsertTailList(&pClAf->ClSapList, &pClSap->Linkage);
|
|
|
|
REF_CL_AF(pClAf);
|
|
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
|
|
//
|
|
// Register the new sap
|
|
//
|
|
Status = NdisClRegisterSap(pClAf->NdisAfHandle,
|
|
pClSap,
|
|
pClSap->CoSap,
|
|
&pClSap->NdisSapHandle);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
PxClRegisterSapComplete(Status,
|
|
pClSap,
|
|
pClSap->CoSap,
|
|
pClSap->NdisSapHandle);
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
DEREF_CL_AF(pClAf);
|
|
|
|
DEREF_TAPILINE(TapiLine);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSetDevConfig(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSetMediaMode(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode =
|
|
(PNDIS_TAPI_SET_MEDIA_MODE)(pNdisTapiRequest->Data);
|
|
|
|
PPX_VC pVc;
|
|
PPX_TAPI_LINE TapiLine;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: enter\n"));
|
|
|
|
if (!IsVcValid(pNdisTapiSetMediaMode->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetMediaMode: pVc invalid call handle %d\n",
|
|
pNdisTapiSetMediaMode->hdCall));
|
|
|
|
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
TapiLine = pVc->TapiAddr->TapiLine;
|
|
|
|
if ((TapiLine->DevCaps->ulMediaModes & pNdisTapiSetMediaMode->ulMediaMode)) {
|
|
pVc->CallInfo->ulMediaMode = pNdisTapiSetMediaMode->ulMediaMode;
|
|
} else {
|
|
Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
|
|
}
|
|
|
|
//
|
|
// Deref for ref applied at entry when
|
|
// validating the vc
|
|
//
|
|
DEREF_VC_LOCKED(pVc);
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: exit\n"));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSetStatusMessages(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSeStatusMessages: enter\n"));
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetStatusMessages: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiOpen(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PNDIS_TAPI_OPEN TapiBuffer =
|
|
(PNDIS_TAPI_OPEN)pNdisTapiRequest->Data;
|
|
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PPX_TAPI_LINE TapiLine;
|
|
PPX_TAPI_ADDR TapiAddr;
|
|
PNDISTAPI_OPENDATA OpenData;
|
|
PX_ADAPTER *Adapter;
|
|
ULONG n;
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: enter\nn"));
|
|
|
|
if (!IsTapiDeviceValid(TapiBuffer->ulDeviceID, &TapiLine)) {
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOPEN: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->ulDeviceID));
|
|
return(NDISTAPIERR_BADDEVICEID);
|
|
}
|
|
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiOpen: got device %p from ID %d\n", TapiLine, TapiBuffer->ulDeviceID));
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
if (!(TapiLine->DevStatus->ulDevStatusFlags &
|
|
LINEDEVSTATUSFLAGS_INSERVICE)) {
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
|
|
return(NDISTAPIERR_DEVICEOFFLINE);
|
|
}
|
|
|
|
//
|
|
// Stick TAPI's line handle into the device
|
|
//
|
|
TapiLine->htLine = (HTAPI_LINE)TapiBuffer->htLine;
|
|
|
|
TapiLine->DevStatus->ulNumOpens++;
|
|
|
|
//
|
|
// Stick our line handle into the out param. This is the context that will be
|
|
// passed to us in subsequent API calls on this open line device. Use the device ID.
|
|
//
|
|
TapiBuffer->hdLine = TapiLine->hdLine;
|
|
|
|
//
|
|
// Stick the miniport GUID and the mediatype into the variable data portion of the
|
|
// TAPI Open call (req'd for NDISWAN/Tonybe)
|
|
//
|
|
Adapter = TapiLine->TapiProvider->Adapter;
|
|
|
|
OpenData = (PNDISTAPI_OPENDATA)
|
|
((PUCHAR)pNdisTapiRequest->Data + sizeof(NDIS_TAPI_OPEN));
|
|
|
|
RtlMoveMemory(&OpenData->Guid,
|
|
&Adapter->Guid,
|
|
sizeof(OpenData->Guid));
|
|
|
|
OpenData->MediaType = Adapter->MediumSubType;
|
|
|
|
DEREF_TAPILINE_LOCKED(TapiLine);
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiProviderInit(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
fea142c4
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiProviderShutdown(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
fea142c4
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
PxTapiSecureCall(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: exit\n"));
|
|
|
|
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiSelectExtVersion(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TAPI OID action routine
|
|
Arguments:
|
|
|
|
pNdisTapiRequest -- the request that arrived in an IRP system buffer
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: enter\n"));
|
|
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: exit\n"));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
PxTapiGatherDigits(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
{
|
|
NDIS_STATUS Status = STATUS_SUCCESS;
|
|
PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits = NULL;
|
|
NDIS_HANDLE NdisBindingHandle, NdisAfHandle, NdisVcHandle;
|
|
PPX_VC pVc = NULL;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiGatherDigits: Enter\n"));
|
|
|
|
pNdisTapiGatherDigits =
|
|
(PNDIS_TAPI_GATHER_DIGITS)pNdisTapiRequest->Data;
|
|
|
|
do {
|
|
PX_REQUEST ProxyRequest;
|
|
PNDIS_REQUEST NdisRequest;
|
|
PIRP Irp;
|
|
|
|
if (!IsVcValid(pNdisTapiGatherDigits->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiGatherDigits: Invalid call - Setting "
|
|
"Status NDISTAPIERR_BADDEVICEID\n"));
|
|
Status = NDISTAPIERR_BADDEVICEID;
|
|
break;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
//
|
|
// If we're monitoring digits (ala lineMonitorDigits) then we can't gather digits.
|
|
//
|
|
if (pVc->ulMonitorDigitsModes != 0) {
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (pVc->PendingGatherDigits != NULL) {
|
|
//
|
|
// Check if the buffer passed to TSPI_lineGatherDigits was NULL. If so, then this
|
|
// is a request to cancel digit gathering that was previously initiated. If not, then
|
|
// the app is trying to do two lineGatherDigits() operations at once and we have to
|
|
// fail this.
|
|
//
|
|
if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
|
|
|
|
pVc->PendingGatherDigits = NULL;
|
|
PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
break;
|
|
} else {
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
|
|
}
|
|
} else if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
|
|
//
|
|
// Trying to cancel digit detection even though it wasn't started. Fail this.
|
|
//
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
Irp = pNdisTapiRequest->Irp;
|
|
|
|
IoSetCancelRoutine(Irp, PxCancelSetQuery);
|
|
|
|
//
|
|
// Store the unique request ID in the VC - this will be used later to retrieve the
|
|
// original IRP.
|
|
//
|
|
pVc->PendingGatherDigits = pNdisTapiRequest;
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
//
|
|
// Initialize the timer that will be used to implement the digit timeouts.
|
|
//
|
|
|
|
NdisInitializeTimer(&pVc->DigitTimer,
|
|
PxDigitTimerRoutine,
|
|
(PVOID)pVc);
|
|
|
|
//
|
|
// Fill out our request structure.
|
|
//
|
|
NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
|
|
|
|
PxInitBlockStruc(&ProxyRequest.Block);
|
|
|
|
NdisRequest = &ProxyRequest.NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestSetInformation;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.Oid =
|
|
OID_CO_TAPI_REPORT_DIGITS;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
|
|
(PVOID)&pNdisTapiGatherDigits->ulDigitModes; // This is the NDIS_TAPI_GATHER_DIGITS structure
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
|
|
sizeof(pNdisTapiGatherDigits->ulDigitModes);
|
|
|
|
Status =
|
|
NdisCoRequest(pVc->Adapter->ClBindingHandle,
|
|
pVc->ClAf->NdisAfHandle,
|
|
pVc->ClVcHandle,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
Status = PxBlock(&ProxyRequest.Block);
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->PendingGatherDigits = NULL;
|
|
|
|
IoSetCancelRoutine(Irp, NULL);
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiGatherDigits: NdisCoRequest failed\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Start the timer for the first digit timeout. Ref the VC here because otherwise it might
|
|
// go away before the timer fires.
|
|
//
|
|
if (pNdisTapiGatherDigits->ulFirstDigitTimeout) {
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
REF_VC(pVc);
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
NdisSetTimer(&pVc->DigitTimer,
|
|
pNdisTapiGatherDigits->ulFirstDigitTimeout);
|
|
}
|
|
|
|
//
|
|
// Set status to pending because this request just initiates the gathering of digits.
|
|
// The IRP will complete once all the digits come in.
|
|
//
|
|
Status = NDIS_STATUS_PENDING;
|
|
|
|
} while (FALSE);
|
|
|
|
DEREF_VC(pVc);
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI,
|
|
("PxTapiGatherDigits: Exit - Returning 0x%x\n", Status));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxTapiMonitorDigits(
|
|
IN PNDISTAPI_REQUEST pNdisTapiRequest
|
|
)
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PNDIS_TAPI_MONITOR_DIGITS pNdisTapiMonitorDigits = NULL;
|
|
PPX_VC pVc = NULL;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Enter\n"));
|
|
|
|
pNdisTapiMonitorDigits =
|
|
(PNDIS_TAPI_MONITOR_DIGITS)pNdisTapiRequest->Data;
|
|
|
|
do {
|
|
if (!IsVcValid(pNdisTapiMonitorDigits->hdCall, &pVc)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiMonitorDigits: Invalid call - Setting "
|
|
"Status NDISTAPIERR_BADDEVICEID\n"));
|
|
Status = NDISTAPIERR_BADDEVICEID;
|
|
break;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
if (pVc->PendingGatherDigits != NULL) {
|
|
//
|
|
// Can't monitor digits while a lineGatherDigits request is in effect.
|
|
//
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
|
|
if (pVc->ulMonitorDigitsModes != 0) {
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
//
|
|
// We are already monitoring digits as a result of lineMonitorDigits request.
|
|
// If the digit modes in the this request are zero, then this is a request to
|
|
// cancel digit monitoring.
|
|
//
|
|
|
|
if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
|
|
|
|
Status = PxStopDigitReporting(pVc);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiMonitorDigits: Failed to stop digit reporting with status 0x%x\n", Status));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// It's a shame that I have to acquire and release again since I had
|
|
// the lock before, but there's no way to know whether I can set this
|
|
// to zero until I know the status that PxStopDigitReporting() returned.
|
|
//
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
pVc->ulMonitorDigitsModes = 0;
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
} else {
|
|
//
|
|
// We're already monitoring digits, so this request to do so must fail.
|
|
//
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
} else {
|
|
PX_REQUEST ProxyRequest;
|
|
PNDIS_REQUEST NdisRequest;
|
|
|
|
pVc->ulMonitorDigitsModes = pNdisTapiMonitorDigits->ulDigitModes;
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
|
|
//
|
|
// Someone's trying to cancel digit monitoring, but it hasn't been started yet.
|
|
//
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Fill out our request structure to tell the miniport to start reporting digits.
|
|
//
|
|
NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
|
|
|
|
PxInitBlockStruc(&ProxyRequest.Block);
|
|
|
|
NdisRequest = &ProxyRequest.NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestSetInformation;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.Oid =
|
|
OID_CO_TAPI_REPORT_DIGITS;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
|
|
(PVOID)&pNdisTapiMonitorDigits->ulDigitModes;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
|
|
sizeof(pNdisTapiMonitorDigits->ulDigitModes);
|
|
|
|
Status =
|
|
NdisCoRequest(pVc->Adapter->ClBindingHandle,
|
|
pVc->ClAf->NdisAfHandle,
|
|
pVc->ClVcHandle,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
Status = PxBlock(&ProxyRequest.Block);
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->ulMonitorDigitsModes = 0;
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxTapiMonitorDigits: NdisCoRequest to start digit reporting failed with status 0x%x\n", Status));
|
|
break;
|
|
}
|
|
|
|
}
|
|
} while (FALSE);
|
|
|
|
DEREF_VC(pVc);
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Exit - Returning 0x%x\n", Status));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
PxTapiCompleteDropIrps(
|
|
IN PPX_VC pVc,
|
|
IN ULONG Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: Vc %p\n", pVc));
|
|
|
|
ASSERT(!IsListEmpty(&pVc->PendingDropReqs));
|
|
ASSERT(pVc->Flags & PX_VC_DROP_PENDING);
|
|
|
|
while (!IsListEmpty(&pVc->PendingDropReqs)) {
|
|
|
|
PLIST_ENTRY Entry;
|
|
PIRP Irp;
|
|
KIRQL Irql;
|
|
PNDISTAPI_REQUEST pNdisTapiRequest;
|
|
|
|
Entry =
|
|
RemoveHeadList(&pVc->PendingDropReqs);
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
pNdisTapiRequest =
|
|
CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
|
|
|
|
Irp = pNdisTapiRequest->Irp;
|
|
|
|
ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
IoSetCancelRoutine(Irp, NULL);
|
|
|
|
Irp->IoStatus.Information =
|
|
sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
}
|
|
|
|
pVc->Flags &= ~PX_VC_DROP_PENDING;
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: exit\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
PxTapiCompleteAllIrps(
|
|
IN PPX_VC pVc,
|
|
IN ULONG Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: Vc %p\n", pVc));
|
|
|
|
while (!IsListEmpty(&pVc->PendingDropReqs)) {
|
|
|
|
PLIST_ENTRY Entry;
|
|
PIRP Irp;
|
|
KIRQL Irql;
|
|
PNDISTAPI_REQUEST pNdisTapiRequest;
|
|
|
|
Entry =
|
|
RemoveHeadList(&pVc->PendingDropReqs);
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
pNdisTapiRequest =
|
|
CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
|
|
|
|
Irp = pNdisTapiRequest->Irp;
|
|
|
|
ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
IoSetCancelRoutine(Irp, NULL);
|
|
|
|
Irp->IoStatus.Information =
|
|
sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
}
|
|
|
|
pVc->Flags &= ~PX_VC_DROP_PENDING;
|
|
|
|
if (pVc->PendingGatherDigits != NULL) {
|
|
|
|
PIRP Irp;
|
|
KIRQL Irql;
|
|
PNDISTAPI_REQUEST pNdisTapiRequest;
|
|
|
|
|
|
pNdisTapiRequest = pVc->PendingGatherDigits;
|
|
pVc->PendingGatherDigits = NULL;
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
Irp = pNdisTapiRequest->Irp;
|
|
|
|
ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
IoSetCancelRoutine(Irp, NULL);
|
|
|
|
Irp->IoStatus.Information =
|
|
sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI,
|
|
("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
}
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: exit\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
PxIndicateStatus(
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to send any event info that may be in the device extension to TAPI in the form of an
|
|
NDIS_TAPI_EVENT, sent in an available queued GET_EVENT IRP. If there's no outstanding IRP, stick
|
|
the data in the queue so it will go whenver there is one.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PIRP Irp;
|
|
PNDIS_TAPI_EVENT NdisTapiEvent;
|
|
PNDISTAPI_EVENT_DATA NdisTapiEventData;
|
|
|
|
NdisTapiEvent = StatusBuffer;
|
|
|
|
//
|
|
// Sync event buf access by acquiring EventSpinLock
|
|
//
|
|
NdisAcquireSpinLock(&TspCB.Lock);
|
|
|
|
//
|
|
// Are we initialized with TAPI?
|
|
//
|
|
if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
|
|
PXDEBUGP(PXD_WARNING, PXM_TAPI,
|
|
("PxIndicateStatus: TAPI not connected!\n"));
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
return;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
NdisAcquireSpinLock(&TspEventList.Lock);
|
|
|
|
Irp = TspEventList.RequestIrp;
|
|
TspEventList.RequestIrp = NULL;
|
|
|
|
if (Irp == NULL) {
|
|
PPROVIDER_EVENT ProviderEvent;
|
|
|
|
ProviderEvent =
|
|
ExAllocateFromNPagedLookasideList(&ProviderEventLookaside);
|
|
|
|
if (ProviderEvent != NULL) {
|
|
RtlMoveMemory(&ProviderEvent->Event,
|
|
StatusBuffer,
|
|
sizeof(NDIS_TAPI_EVENT));
|
|
|
|
InsertTailList(&TspEventList.List,
|
|
&ProviderEvent->Linkage);
|
|
|
|
TspEventList.Count++;
|
|
|
|
if (TspEventList.Count > TspEventList.MaxCount) {
|
|
TspEventList.MaxCount = TspEventList.Count;
|
|
}
|
|
|
|
}
|
|
} else {
|
|
ASSERT(IsListEmpty(&TspEventList.List));
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TspEventList.Lock);
|
|
|
|
//
|
|
// Check of there is an outstanding request to satisfy
|
|
//
|
|
if (Irp != NULL) {
|
|
KIRQL Irql;
|
|
|
|
//
|
|
// Clear out the cancel routine
|
|
//
|
|
IoSetCancelRoutine (Irp, NULL);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information =
|
|
sizeof(NDISTAPI_EVENT_DATA) + StatusBufferSize - 1;
|
|
|
|
//
|
|
// Copy as much of the input data possible from the input data
|
|
// queue to the SystemBuffer to satisfy the read.
|
|
//
|
|
NdisTapiEventData = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
ASSERT(NdisTapiEventData->ulTotalSize >= StatusBufferSize);
|
|
|
|
RtlMoveMemory(NdisTapiEventData->Data,
|
|
(PCHAR) StatusBuffer,
|
|
StatusBufferSize);
|
|
|
|
//
|
|
// Set the flag so that we start the next packet and complete
|
|
// this read request (with STATUS_SUCCESS) prior to return.
|
|
//
|
|
|
|
NdisTapiEventData->ulUsedSize = StatusBufferSize;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI,
|
|
("PxIndicateStatus: htLine: %x, htCall: %x, Msg: %x\n",
|
|
NdisTapiEvent->htLine, NdisTapiEvent->htCall, NdisTapiEvent->ulMsg));
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI,
|
|
(" : p1: %x, p2: %x, p3: %x\n",
|
|
NdisTapiEvent->ulParam1, NdisTapiEvent->ulParam2, NdisTapiEvent->ulParam3));
|
|
|
|
IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
|
|
|
|
}
|
|
}
|
|
|
|
NDIS_STATUS
|
|
AllocateTapiResources(
|
|
IN PPX_ADAPTER ClAdapter,
|
|
IN PPX_CL_AF pClAf
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
ULONG SizeNeeded;
|
|
ULONG TapiVersion;
|
|
PPX_TAPI_LINE TapiLine = NULL;
|
|
PPX_TAPI_ADDR TapiAddr = NULL;
|
|
UINT i, j;
|
|
PPX_TAPI_PROVIDER TapiProvider;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiResoures: Enter\n"));
|
|
|
|
//
|
|
// See if this device supports TAPI and if so
|
|
// see how many lines it has
|
|
//
|
|
TapiProvider =
|
|
AllocateTapiProvider(ClAdapter, pClAf);
|
|
|
|
if (TapiProvider == NULL) {
|
|
PXDEBUGP(PXD_ERROR, PXM_TAPI, ("Error allocating TapiProvider!\n"));
|
|
return (NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
PPX_TAPI_PROVIDER
|
|
AllocateTapiProvider(
|
|
PPX_ADAPTER ClAdapter,
|
|
PPX_CL_AF pClAf
|
|
)
|
|
{
|
|
PNDIS_REQUEST NdisRequest;
|
|
NDIS_STATUS Status;
|
|
CO_TAPI_CM_CAPS CmCaps;
|
|
BOOLEAN TapiSupported = TRUE;
|
|
ULONG AllocSize;
|
|
PTAPI_LINE_TABLE LineTable;
|
|
PPX_TAPI_PROVIDER TapiProvider = NULL;
|
|
ULONG i;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiProvider: Enter\n"));
|
|
|
|
do {
|
|
PX_REQUEST ProxyRequest;
|
|
PPX_REQUEST pProxyRequest = &ProxyRequest;
|
|
|
|
NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
|
|
NdisZeroMemory(&CmCaps, sizeof(CmCaps));
|
|
|
|
PxInitBlockStruc (&pProxyRequest->Block);
|
|
|
|
NdisRequest = &pProxyRequest->NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestQueryInformation;
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid =
|
|
OID_CO_TAPI_CM_CAPS;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
|
|
&CmCaps;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
|
|
sizeof(CmCaps);
|
|
|
|
Status =
|
|
NdisCoRequest(ClAdapter->ClBindingHandle,
|
|
pClAf->NdisAfHandle,
|
|
NULL,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
Status = PxBlock(&pProxyRequest->Block);
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
if (Status != NDIS_STATUS_NOT_SUPPORTED) {
|
|
break;
|
|
}
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
//
|
|
// Setup a default config for this device.
|
|
// ToDo! These values should be read from
|
|
// the registry on a per device basis!
|
|
//
|
|
CmCaps.ulNumLines = 1;
|
|
CmCaps.ulFlags = 0;
|
|
CmCaps.ulCoTapiVersion = CO_TAPI_VERSION;
|
|
TapiSupported = FALSE;
|
|
}
|
|
|
|
//
|
|
// Allocate a tapi provider block for this adapter
|
|
// The provider block will live outside of the
|
|
// adapter. This allows us to continue tapi service
|
|
// after a machine has been power managed.
|
|
//
|
|
|
|
AllocSize = sizeof(PX_TAPI_PROVIDER) +
|
|
(sizeof(PPX_TAPI_LINE) * CmCaps.ulNumLines) +
|
|
sizeof(PVOID);
|
|
|
|
PxAllocMem(TapiProvider, AllocSize, PX_PROVIDER_TAG);
|
|
|
|
if (TapiProvider == NULL) {
|
|
break;
|
|
}
|
|
|
|
NdisZeroMemory(TapiProvider, AllocSize);
|
|
|
|
NdisAllocateSpinLock(&TapiProvider->Lock);
|
|
|
|
TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
|
|
|
|
TapiProvider->Adapter = ClAdapter;
|
|
TapiProvider->ClAf = pClAf;
|
|
TapiProvider->NumDevices = CmCaps.ulNumLines;
|
|
TapiProvider->Guid = ClAdapter->Guid;
|
|
TapiProvider->Af = pClAf->Af;
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider Allocated: GUID %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x\n",
|
|
TapiProvider->Guid.Data1, TapiProvider->Guid.Data2, TapiProvider->Guid.Data3,
|
|
TapiProvider->Guid.Data4[0],TapiProvider->Guid.Data4[1],TapiProvider->Guid.Data4[2],
|
|
TapiProvider->Guid.Data4[3],TapiProvider->Guid.Data4[4],TapiProvider->Guid.Data4[5],
|
|
TapiProvider->Guid.Data4[6],TapiProvider->Guid.Data4[7]));
|
|
|
|
TapiProvider->TapiSupported = TapiSupported;
|
|
|
|
TapiProvider->TapiFlags |= CmCaps.ulFlags;
|
|
|
|
TapiProvider->CoTapiVersion = CmCaps.ulCoTapiVersion;
|
|
|
|
InitializeListHead(&TapiProvider->LineList);
|
|
InitializeListHead(&TapiProvider->CreateList);
|
|
|
|
for (i = 0; i < TapiProvider->NumDevices; i++) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine =
|
|
AllocateTapiLine(TapiProvider, i);
|
|
|
|
if (TapiLine == NULL) {
|
|
FreeTapiProvider(TapiProvider);
|
|
TapiProvider = NULL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Put the new line on the create list
|
|
// We will need to insert it in the line table
|
|
// and possibly notify tapi about it
|
|
//
|
|
InsertTailList(&TapiProvider->CreateList, &TapiLine->Linkage);
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (TapiProvider != NULL) {
|
|
PPX_TAPI_PROVIDER tp;
|
|
BOOLEAN TapiConnected;
|
|
|
|
//
|
|
// See if we already have a provider for this
|
|
// GUID. If we don't just add this provider on
|
|
// to the tsp and do the right thing with it's
|
|
// new lines. If we do see if anything on the
|
|
// provider has changed and do the right thing
|
|
// with it's tapi lines.
|
|
//
|
|
NdisAcquireSpinLock(&TspCB.Lock);
|
|
|
|
tp = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
|
|
|
|
while ((PVOID)tp != (PVOID)&TspCB.ProviderList) {
|
|
|
|
if ((tp->Status == PROVIDER_STATUS_OFFLINE) &&
|
|
(NdisEqualMemory(&tp->Guid, &TapiProvider->Guid, sizeof(tp->Guid))) &&
|
|
(pClAf->Af.AddressFamily == tp->Af.AddressFamily)) {
|
|
|
|
//
|
|
// We have already have a provider for this
|
|
// adapter/address family. See if anything has
|
|
// changed.
|
|
//
|
|
//
|
|
// ToDo!
|
|
// This check needs to be more complete!
|
|
//
|
|
if (tp->NumDevices != TapiProvider->NumDevices) {
|
|
//
|
|
// ToDo!
|
|
// Much work to do here!
|
|
//
|
|
|
|
} else {
|
|
//
|
|
// Nothing has changed so free the new allocations
|
|
// and reactivate the old ones.
|
|
//
|
|
|
|
FreeTapiProvider(TapiProvider);
|
|
|
|
TapiProvider = tp;
|
|
}
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider found: GUID %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x\n",
|
|
ClAdapter->Guid.Data1, ClAdapter->Guid.Data2, ClAdapter->Guid.Data3,
|
|
ClAdapter->Guid.Data4[0],ClAdapter->Guid.Data4[1],ClAdapter->Guid.Data4[2],
|
|
ClAdapter->Guid.Data4[3],ClAdapter->Guid.Data4[4],ClAdapter->Guid.Data4[5],
|
|
ClAdapter->Guid.Data4[6],ClAdapter->Guid.Data4[7]));
|
|
break;
|
|
|
|
} else {
|
|
|
|
tp = (PPX_TAPI_PROVIDER)tp->Linkage.Flink;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We did not find a provider on the list
|
|
// so insert the new provider
|
|
//
|
|
if ((PVOID)tp == (PVOID)&TspCB.ProviderList) {
|
|
InsertTailList(&TspCB.ProviderList, &TapiProvider->Linkage);
|
|
TspCB.NdisTapiNumDevices += TapiProvider->NumDevices;
|
|
}
|
|
|
|
if (TspCB.Status == NDISTAPI_STATUS_CONNECTED) {
|
|
TapiProvider->Status = PROVIDER_STATUS_ONLINE;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
NdisAcquireSpinLock(&TapiProvider->Lock);
|
|
|
|
pClAf->TapiProvider = TapiProvider;
|
|
TapiProvider->ClAf= pClAf;
|
|
TapiProvider->Adapter = ClAdapter;
|
|
|
|
while (!IsListEmpty(&TapiProvider->CreateList)) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = (PPX_TAPI_LINE)
|
|
RemoveHeadList(&TapiProvider->CreateList);
|
|
|
|
InsertTailList(&TapiProvider->LineList, &TapiLine->Linkage);
|
|
|
|
//
|
|
// Insert the line in the table
|
|
//
|
|
if (!InsertLineInTable(TapiLine)) {
|
|
FreeTapiLine(TapiLine);
|
|
continue;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TapiProvider->Lock);
|
|
|
|
SendTapiLineCreate(TapiLine);
|
|
|
|
NdisAcquireSpinLock(&TapiProvider->Lock);
|
|
}
|
|
|
|
MarkProviderOnline(TapiProvider);
|
|
|
|
NdisReleaseSpinLock(&TapiProvider->Lock);
|
|
}
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider: %x\n", TapiProvider));
|
|
|
|
return (TapiProvider);
|
|
}
|
|
|
|
VOID
|
|
MarkProviderOffline(
|
|
PPX_TAPI_PROVIDER TapiProvider
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
|
|
TapiProvider->ClAf = NULL;
|
|
TapiProvider->Adapter = NULL;
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = LineTable.Table[i];
|
|
|
|
if (TapiLine != NULL) {
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
if (TapiLine->TapiProvider == TapiProvider) {
|
|
|
|
TapiLine->DevStatus->ulDevStatusFlags &=
|
|
~(LINEDEVSTATUSFLAGS_INSERVICE);
|
|
|
|
TapiLine->ClAf = NULL;
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
|
|
#if 0
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
|
|
SendTapiLineClose(TapiLine);
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
#endif
|
|
|
|
} else {
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
}
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
}
|
|
|
|
VOID
|
|
MarkProviderOnline(
|
|
PPX_TAPI_PROVIDER TapiProvider
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
TapiProvider->Status = PROVIDER_STATUS_ONLINE;
|
|
|
|
NdisReleaseSpinLock(&TapiProvider->Lock);
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = LineTable.Table[i];
|
|
|
|
if (TapiLine != NULL) {
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
if (TapiLine->TapiProvider == TapiProvider) {
|
|
|
|
TapiLine->DevStatus->ulDevStatusFlags |=
|
|
LINEDEVSTATUSFLAGS_INSERVICE;
|
|
|
|
TapiLine->ClAf = TapiProvider->ClAf;
|
|
|
|
//#if 0
|
|
//
|
|
// This line was open by tapi before it was
|
|
// marked offline. We need to force tapi to
|
|
// reopen the line so we will send the CLOSE_LINE
|
|
// message in the hopes that any apps that care
|
|
// will then turn around and reopen the line.
|
|
//
|
|
if (TapiLine->DevStatus->ulNumOpens != 0) {
|
|
// TapiLine->DevStatus->ulNumOpens = 0;
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
|
|
SendTapiLineClose(TapiLine);
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
}
|
|
//#endif
|
|
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
|
|
NdisAcquireSpinLock(&TapiProvider->Lock);
|
|
}
|
|
|
|
|
|
VOID
|
|
MarkProviderConnected(
|
|
PPX_TAPI_PROVIDER TapiProvider
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = LineTable.Table[i];
|
|
|
|
if (TapiLine != NULL) {
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
if (TapiLine->TapiProvider == TapiProvider) {
|
|
|
|
TapiLine->DevStatus->ulDevStatusFlags |=
|
|
LINEDEVSTATUSFLAGS_CONNECTED;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
}
|
|
|
|
VOID
|
|
MarkProviderDisconnected(
|
|
PPX_TAPI_PROVIDER TapiProvider
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
//
|
|
// ToDo! If we have any active calls on this line we
|
|
// need to disconnect them without tapi's assistance. This
|
|
// would only happen if tapi crashes while we have active calls
|
|
//
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = LineTable.Table[i];
|
|
|
|
if (TapiLine != NULL) {
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
if (TapiLine->TapiProvider == TapiProvider) {
|
|
|
|
TapiLine->DevStatus->ulDevStatusFlags &=
|
|
~(LINEDEVSTATUSFLAGS_CONNECTED);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
}
|
|
|
|
VOID
|
|
ClearSapWithTapiLine(
|
|
PPX_CL_SAP pClSap
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = LineTable.Table[i];
|
|
|
|
if (TapiLine != NULL) {
|
|
|
|
NdisAcquireSpinLock(&TapiLine->Lock);
|
|
|
|
if (TapiLine->ClSap == pClSap) {
|
|
TapiLine->ClSap = NULL;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TapiLine->Lock);
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeTapiProvider(
|
|
PPX_TAPI_PROVIDER TapiProvider
|
|
)
|
|
{
|
|
//
|
|
// Free any lines on the create list
|
|
//
|
|
while (!IsListEmpty(&TapiProvider->CreateList)) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = (PPX_TAPI_LINE)
|
|
RemoveHeadList(&TapiProvider->CreateList);
|
|
|
|
FreeTapiLine(TapiLine);
|
|
}
|
|
|
|
//
|
|
// Free the lines associated with this provider
|
|
//
|
|
while (!IsListEmpty(&TapiProvider->LineList)) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = (PPX_TAPI_LINE)
|
|
RemoveHeadList(&TapiProvider->LineList);
|
|
|
|
if (TapiLine->Flags & PX_LINE_IN_TABLE) {
|
|
RemoveTapiLineFromTable(TapiLine);
|
|
}
|
|
|
|
FreeTapiLine(TapiLine);
|
|
}
|
|
|
|
NdisFreeSpinLock(&TapiProvider->Lock);
|
|
|
|
PxFreeMem(TapiProvider);
|
|
}
|
|
|
|
PPX_TAPI_LINE
|
|
AllocateTapiLine(
|
|
PPX_TAPI_PROVIDER TapiProvider,
|
|
ULONG LineNumber
|
|
)
|
|
{
|
|
PLINE_DEV_CAPS ldc, ldc1;
|
|
PNDIS_REQUEST NdisRequest;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PCO_TAPI_LINE_CAPS LineCaps;
|
|
PUCHAR EnumBuffer;
|
|
#if DBG
|
|
ULONG EnumBufferSize = PAGE_SIZE -
|
|
sizeof(PXD_ALLOCATION);
|
|
#else
|
|
ULONG EnumBufferSize = PAGE_SIZE;
|
|
#endif
|
|
ULONG SizeNeeded, SizeDevCaps;
|
|
PPX_TAPI_LINE TapiLine = NULL;
|
|
PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
|
|
PPX_CL_AF pClAf = TapiProvider->ClAf;
|
|
ULONG i;
|
|
PX_REQUEST ProxyRequest;
|
|
PPX_REQUEST pProxyRequest = &ProxyRequest;
|
|
|
|
PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
|
|
|
|
if (EnumBuffer == NULL) {
|
|
return (NULL);
|
|
}
|
|
|
|
NdisZeroMemory(EnumBuffer, EnumBufferSize);
|
|
|
|
LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
|
|
|
|
LineCaps->ulLineID = LineNumber;
|
|
|
|
ldc = &LineCaps->LineDevCaps;
|
|
|
|
ldc->ulTotalSize =
|
|
EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
|
|
|
|
//
|
|
// If this device does not support TAPI we will build
|
|
// a default line configuration.
|
|
// ToDo! Some of these values should be queried from
|
|
// the registry on a per device basis!
|
|
//
|
|
if (!TapiProvider->TapiSupported) {
|
|
NDIS_CO_LINK_SPEED SpeedInfo;
|
|
|
|
LineCaps->ulFlags = 0;
|
|
|
|
ldc->ulTotalSize =
|
|
ldc->ulNeededSize =
|
|
ldc->ulUsedSize =
|
|
sizeof(LINE_DEV_CAPS);
|
|
ldc->ulStringFormat = STRINGFORMAT_ASCII;
|
|
ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
|
|
ldc->ulNumAddresses = 1;
|
|
ldc->ulBearerModes = LINEBEARERMODE_VOICE |
|
|
LINEBEARERMODE_DATA;
|
|
ldc->ulMediaModes = LINEMEDIAMODE_DIGITALDATA;
|
|
ldc->ulMaxNumActiveCalls = 1000;
|
|
|
|
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
|
|
|
|
PxInitBlockStruc (&pProxyRequest->Block);
|
|
|
|
NdisRequest = &pProxyRequest->NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestQueryInformation;
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid =
|
|
OID_GEN_CO_LINK_SPEED;
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
|
|
&SpeedInfo;
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
|
|
sizeof(NDIS_CO_LINK_SPEED);
|
|
|
|
PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: DeviceExtension->RegistryFlags = %x\n", DeviceExtension->RegistryFlags));
|
|
|
|
PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: using ndisrequest to get rates from adapter\n"));
|
|
|
|
Status =
|
|
NdisCoRequest(ClAdapter->ClBindingHandle,
|
|
pClAf->NdisAfHandle,
|
|
NULL,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
Status = PxBlock(&pProxyRequest->Block);
|
|
}
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
ldc->ulMaxRate = SpeedInfo.Outbound;
|
|
} else {
|
|
ldc->ulMaxRate = 128000;
|
|
}
|
|
|
|
} else if (!(TapiProvider->TapiFlags & CO_TAPI_FLAG_PER_LINE_CAPS) &&
|
|
(LineNumber > 0)) {
|
|
|
|
PLINE_DEV_CAPS ldc1;
|
|
PCO_TAPI_LINE_CAPS LineCaps1;
|
|
PPX_TAPI_LINE Line1;
|
|
|
|
//
|
|
// If all of the lines on this device have the same caps
|
|
// and this is not the first line, just copy the caps
|
|
// from the first line!
|
|
//
|
|
Line1 = (PPX_TAPI_LINE)
|
|
TapiProvider->CreateList.Flink;
|
|
|
|
ldc1 = Line1->DevCaps;
|
|
|
|
if (ldc1->ulTotalSize > ldc->ulTotalSize) {
|
|
|
|
//
|
|
// We don't have enough memory allocated!
|
|
//
|
|
PxFreeMem(EnumBuffer);
|
|
|
|
EnumBufferSize =
|
|
(sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS) +
|
|
ldc1->ulTotalSize);
|
|
|
|
PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
|
|
|
|
if (EnumBuffer == NULL){
|
|
return (NULL);
|
|
}
|
|
|
|
NdisZeroMemory(EnumBuffer, EnumBufferSize);
|
|
|
|
LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
|
|
LineCaps->ulLineID = LineNumber;
|
|
LineCaps->LineDevCaps.ulTotalSize =
|
|
EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) -
|
|
sizeof(LINE_DEV_CAPS));
|
|
|
|
ldc = &LineCaps->LineDevCaps;
|
|
}
|
|
|
|
NdisMoveMemory(ldc, ldc1, ldc1->ulUsedSize);
|
|
|
|
} else {
|
|
|
|
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
|
|
|
|
PxInitBlockStruc (&pProxyRequest->Block);
|
|
|
|
NdisRequest = &pProxyRequest->NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestQueryInformation;
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid =
|
|
OID_CO_TAPI_LINE_CAPS;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
|
|
LineCaps;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
|
|
EnumBufferSize;
|
|
|
|
Status =
|
|
NdisCoRequest(ClAdapter->ClBindingHandle,
|
|
pClAf->NdisAfHandle,
|
|
NULL,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
Status = PxBlock(&pProxyRequest->Block);
|
|
}
|
|
|
|
if (Status == NDIS_STATUS_INVALID_LENGTH){
|
|
ULONG SizeNeeded;
|
|
|
|
//
|
|
// Our buffer was not large enough so try again
|
|
//
|
|
SizeNeeded =
|
|
EnumBufferSize =
|
|
MAX (LineCaps->LineDevCaps.ulNeededSize,
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
|
|
|
|
PxFreeMem(EnumBuffer);
|
|
|
|
PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
|
|
|
|
if (EnumBuffer == NULL){
|
|
return(NULL);
|
|
}
|
|
|
|
NdisZeroMemory(EnumBuffer, EnumBufferSize);
|
|
|
|
LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
|
|
LineCaps->ulLineID = LineNumber;
|
|
|
|
ldc = &LineCaps->LineDevCaps;
|
|
|
|
ldc->ulTotalSize =
|
|
EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
|
|
|
|
NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
|
|
|
|
PxInitBlockStruc (&pProxyRequest->Block);
|
|
|
|
NdisRequest = &pProxyRequest->NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestQueryInformation;
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid =
|
|
OID_CO_TAPI_LINE_CAPS;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
|
|
LineCaps;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
|
|
EnumBufferSize;
|
|
|
|
Status =
|
|
NdisCoRequest(ClAdapter->ClBindingHandle,
|
|
pClAf->NdisAfHandle,
|
|
NULL,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING){
|
|
Status = PxBlock(&pProxyRequest->Block);
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS){
|
|
PxFreeMem(EnumBuffer);
|
|
return(NULL);
|
|
}
|
|
|
|
}else if (Status != STATUS_SUCCESS){
|
|
PxFreeMem(EnumBuffer);
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
SizeNeeded = sizeof(PX_TAPI_LINE);
|
|
SizeNeeded +=
|
|
(sizeof(PPX_TAPI_ADDR) * LineCaps->LineDevCaps.ulNumAddresses);
|
|
SizeNeeded += sizeof(LINE_DEV_STATUS);
|
|
SizeNeeded += 3*sizeof(PVOID);
|
|
|
|
if (LineCaps->LineDevCaps.ulUsedSize < sizeof(LINE_DEV_CAPS)) {
|
|
LineCaps->LineDevCaps.ulUsedSize = sizeof(LINE_DEV_CAPS);
|
|
}
|
|
|
|
SizeDevCaps = LineCaps->LineDevCaps.ulUsedSize;
|
|
|
|
SizeNeeded += SizeDevCaps;
|
|
|
|
PxAllocMem(TapiLine, SizeNeeded, PX_TAPILINE_TAG);
|
|
|
|
if (TapiLine == NULL){
|
|
PxFreeMem(EnumBuffer);
|
|
return(NULL);
|
|
}
|
|
|
|
NdisZeroMemory(TapiLine, SizeNeeded);
|
|
|
|
TapiLine->DevCaps = (PLINE_DEV_CAPS)
|
|
((PUCHAR)TapiLine + sizeof(PX_TAPI_LINE) + sizeof(PVOID));
|
|
|
|
(ULONG_PTR)TapiLine->DevCaps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
|
|
|
|
TapiLine->DevStatus = (PLINE_DEV_STATUS)
|
|
((PUCHAR)TapiLine->DevCaps + SizeDevCaps + sizeof(PVOID));
|
|
|
|
(ULONG_PTR)TapiLine->DevStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
|
|
|
|
TapiLine->AddrTable.Table = (PPX_TAPI_ADDR*)
|
|
((PUCHAR)TapiLine->DevStatus +
|
|
sizeof(LINE_DEV_STATUS) + sizeof(PVOID));
|
|
|
|
(ULONG_PTR)TapiLine->AddrTable.Table &= ~((ULONG_PTR)sizeof(PVOID) - 1);
|
|
|
|
NdisMoveMemory(TapiLine->DevCaps,
|
|
&LineCaps->LineDevCaps,
|
|
LineCaps->LineDevCaps.ulUsedSize);
|
|
|
|
ldc = TapiLine->DevCaps;
|
|
|
|
//
|
|
// Proxy fills some fields on behalf of all cm/miniports
|
|
//
|
|
ldc->ulPermanentLineID =
|
|
TapiProvider->Guid.Data1 + LineNumber;
|
|
ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
|
|
ldc->ulAnswerMode = LINEANSWERMODE_NONE;
|
|
ldc->ulLineStates = LINEDEVSTATE_CONNECTED |
|
|
LINEDEVSTATE_DISCONNECTED |
|
|
LINEDEVSTATE_OPEN |
|
|
LINEDEVSTATE_CLOSE |
|
|
LINEDEVSTATE_INSERVICE |
|
|
LINEDEVSTATE_OUTOFSERVICE |
|
|
LINEDEVSTATE_REMOVED;
|
|
ldc->ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
|
|
ldc->PermanentLineGuid = TapiProvider->Guid;
|
|
|
|
ldc->ulTotalSize =
|
|
ldc->ulNeededSize =
|
|
ldc->ulUsedSize;
|
|
|
|
TapiLine->TapiProvider = TapiProvider;
|
|
TapiLine->CmLineID = LineNumber;
|
|
TapiLine->Flags |= LineCaps->ulFlags;
|
|
TapiLine->DevStatus->ulTotalSize =
|
|
TapiLine->DevStatus->ulNeededSize =
|
|
TapiLine->DevStatus->ulUsedSize = sizeof(LINE_DEV_STATUS);
|
|
TapiLine->ClAf = pClAf;
|
|
TapiLine->RefCount= 1;
|
|
|
|
//
|
|
// Build the address table for this line
|
|
//
|
|
InitializeListHead(&TapiLine->AddrTable.List);
|
|
|
|
NdisAllocateSpinLock(&TapiLine->Lock);
|
|
|
|
TapiLine->AddrTable.Size = TapiLine->DevCaps->ulNumAddresses;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("Allocated TapiLine %p LineId %d \n", TapiLine, TapiLine->CmLineID));
|
|
|
|
for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++) {
|
|
PPX_TAPI_ADDR TapiAddr;
|
|
|
|
TapiAddr =
|
|
AllocateTapiAddr(TapiProvider, TapiLine, i);
|
|
|
|
if (TapiAddr == NULL) {
|
|
FreeTapiLine(TapiLine);
|
|
TapiLine = NULL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Insert the address in the line's address table
|
|
//
|
|
TapiLine->AddrTable.Table[i] = TapiAddr;
|
|
InsertTailList(&TapiLine->AddrTable.List,
|
|
&TapiAddr->Linkage);
|
|
TapiLine->AddrTable.Count++;
|
|
}
|
|
|
|
PxFreeMem(EnumBuffer);
|
|
|
|
return (TapiLine);
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeTapiLine(
|
|
PPX_TAPI_LINE TapiLine
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++){
|
|
PPX_TAPI_ADDR TapiAddr;
|
|
|
|
//
|
|
// Remove the address from the line table
|
|
//
|
|
TapiAddr = TapiLine->AddrTable.Table[i];
|
|
|
|
if (TapiAddr != NULL) {
|
|
|
|
RemoveEntryList(&TapiAddr->Linkage);
|
|
TapiLine->AddrTable.Table[i] = NULL;
|
|
TapiLine->AddrTable.Count--;
|
|
|
|
//
|
|
// Free the address memory
|
|
//
|
|
FreeTapiAddr(TapiAddr);
|
|
}
|
|
}
|
|
|
|
NdisFreeSpinLock(&TapiLine->Lock);
|
|
|
|
//
|
|
// Free the line memory
|
|
//
|
|
PxFreeMem(TapiLine);
|
|
}
|
|
|
|
|
|
PPX_TAPI_ADDR
|
|
AllocateTapiAddr(
|
|
PPX_TAPI_PROVIDER TapiProvider,
|
|
PPX_TAPI_LINE TapiLine,
|
|
ULONG AddrID
|
|
)
|
|
{
|
|
PPX_TAPI_ADDR TapiAddr;
|
|
PUCHAR EnumBuffer;
|
|
#if DBG
|
|
ULONG EnumBufferSize = PAGE_SIZE -
|
|
sizeof(PXD_ALLOCATION);
|
|
#else
|
|
ULONG EnumBufferSize = PAGE_SIZE;
|
|
#endif
|
|
PNDIS_REQUEST NdisRequest;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
ULONG SizeNeeded;
|
|
PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
|
|
PPX_CL_AF pClAf = TapiProvider->ClAf;
|
|
PX_REQUEST ProxyRequest;
|
|
PPX_REQUEST pProxyRequest = &ProxyRequest;
|
|
PLINE_ADDRESS_CAPS ac;
|
|
PCO_TAPI_ADDRESS_CAPS AddrCaps;
|
|
|
|
PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
|
|
|
|
if (EnumBuffer == NULL){
|
|
return(NULL);
|
|
}
|
|
|
|
NdisZeroMemory(EnumBuffer, EnumBufferSize);
|
|
|
|
AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
|
|
AddrCaps->ulLineID = TapiLine->CmLineID;
|
|
AddrCaps->ulAddressID = AddrID;
|
|
|
|
ac = &AddrCaps->LineAddressCaps;
|
|
|
|
ac->ulTotalSize =
|
|
EnumBufferSize - (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
|
|
|
|
//
|
|
// If this device does not support TAPI we will
|
|
// build a default address.
|
|
// ToDo! Some of these values should be queried from
|
|
// the registry on a per device basis!
|
|
//
|
|
if (!TapiProvider->TapiSupported){
|
|
ac->ulTotalSize =
|
|
ac->ulNeededSize =
|
|
ac->ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
|
|
ac->ulMaxNumActiveCalls = 1000;
|
|
|
|
}else if (!(TapiLine->Flags & CO_TAPI_FLAG_PER_ADDRESS_CAPS) &&
|
|
(AddrID > 0)){
|
|
|
|
PLINE_ADDRESS_CAPS ac1;
|
|
PCO_TAPI_ADDRESS_CAPS AddrCaps1;
|
|
PPX_TAPI_ADDR Addr1;
|
|
|
|
//
|
|
// If all of the addresses on this line have the same
|
|
// caps and this is not the first address, just copy
|
|
// the caps from the first address!
|
|
//
|
|
Addr1 = (PPX_TAPI_ADDR)
|
|
TapiLine->AddrTable.List.Flink;
|
|
|
|
ac1 = Addr1->Caps;
|
|
|
|
if (ac1->ulTotalSize > ac->ulTotalSize){
|
|
|
|
//
|
|
// We don't have enough memory allocated!
|
|
//
|
|
PxFreeMem(EnumBuffer);
|
|
|
|
EnumBufferSize =
|
|
(sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS) +
|
|
ac1->ulTotalSize);
|
|
|
|
PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
|
|
|
|
if (EnumBuffer == NULL){
|
|
return (NULL);
|
|
}
|
|
|
|
NdisZeroMemory(EnumBuffer, EnumBufferSize);
|
|
|
|
AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
|
|
AddrCaps->ulLineID = TapiLine->CmLineID;
|
|
AddrCaps->ulAddressID = AddrID;
|
|
AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
|
|
(sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
|
|
}
|
|
|
|
ac = &AddrCaps->LineAddressCaps;
|
|
|
|
NdisMoveMemory(ac, ac1, ac1->ulUsedSize);
|
|
|
|
}else{
|
|
|
|
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
|
|
|
|
PxInitBlockStruc (&pProxyRequest->Block);
|
|
|
|
NdisRequest = &pProxyRequest->NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestQueryInformation;
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid =
|
|
OID_CO_TAPI_ADDRESS_CAPS;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
|
|
AddrCaps;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
|
|
EnumBufferSize;
|
|
|
|
Status =
|
|
NdisCoRequest(ClAdapter->ClBindingHandle,
|
|
pClAf->NdisAfHandle,
|
|
NULL,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING){
|
|
Status = PxBlock(&pProxyRequest->Block);
|
|
}
|
|
|
|
if (Status == NDIS_STATUS_INVALID_LENGTH){
|
|
|
|
//
|
|
// Our buffer was not large enough so try again
|
|
//
|
|
SizeNeeded =
|
|
EnumBufferSize =
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
|
|
|
|
PxFreeMem(EnumBuffer);
|
|
|
|
PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
|
|
|
|
if (EnumBuffer == NULL){
|
|
return(NULL);
|
|
}
|
|
|
|
NdisZeroMemory(EnumBuffer, EnumBufferSize);
|
|
|
|
AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
|
|
AddrCaps->ulLineID = TapiLine->CmLineID;
|
|
AddrCaps->ulAddressID = AddrID;
|
|
AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
|
|
(sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
|
|
|
|
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
|
|
|
|
PxInitBlockStruc (&pProxyRequest->Block);
|
|
|
|
NdisRequest = &pProxyRequest->NdisRequest;
|
|
|
|
NdisRequest->RequestType =
|
|
NdisRequestQueryInformation;
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid =
|
|
OID_CO_TAPI_ADDRESS_CAPS;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
|
|
AddrCaps;
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
|
|
EnumBufferSize;
|
|
|
|
Status =
|
|
NdisCoRequest(ClAdapter->ClBindingHandle,
|
|
pClAf->NdisAfHandle,
|
|
NULL,
|
|
NULL,
|
|
NdisRequest);
|
|
|
|
if (Status == NDIS_STATUS_PENDING){
|
|
Status = PxBlock(&pProxyRequest->Block);
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS){
|
|
PxFreeMem(EnumBuffer);
|
|
return(NULL);
|
|
}
|
|
|
|
}else if (Status != STATUS_SUCCESS){
|
|
PxFreeMem(EnumBuffer);
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
if (AddrCaps->LineAddressCaps.ulUsedSize < sizeof(LINE_ADDRESS_CAPS)) {
|
|
AddrCaps->LineAddressCaps.ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
|
|
}
|
|
|
|
SizeNeeded = sizeof(PX_TAPI_ADDR);
|
|
SizeNeeded += AddrCaps->LineAddressCaps.ulUsedSize;
|
|
SizeNeeded += sizeof(LINE_ADDRESS_STATUS);
|
|
SizeNeeded += 2*sizeof(PVOID);
|
|
|
|
PxAllocMem(TapiAddr, SizeNeeded, PX_TAPIADDR_TAG);
|
|
|
|
if (TapiAddr == NULL){
|
|
PxFreeMem(EnumBuffer);
|
|
return (NULL);
|
|
}
|
|
|
|
NdisZeroMemory((PUCHAR)TapiAddr, SizeNeeded);
|
|
|
|
TapiAddr->Caps = (PLINE_ADDRESS_CAPS)
|
|
((PUCHAR)TapiAddr + sizeof(PX_TAPI_ADDR) + sizeof(PVOID));
|
|
|
|
(ULONG_PTR)TapiAddr->Caps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
|
|
|
|
TapiAddr->AddrStatus = (PLINE_ADDRESS_STATUS)
|
|
((PUCHAR)TapiAddr->Caps +
|
|
AddrCaps->LineAddressCaps.ulUsedSize + sizeof(PVOID));
|
|
|
|
(ULONG_PTR)TapiAddr->AddrStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
|
|
|
|
NdisMoveMemory(TapiAddr->Caps,
|
|
&AddrCaps->LineAddressCaps,
|
|
AddrCaps->LineAddressCaps.ulUsedSize);
|
|
|
|
//
|
|
// Proxy fills some fields on behalf of all cm/miniports
|
|
//
|
|
ac = TapiAddr->Caps;
|
|
|
|
if (ac->ulTotalSize < ac->ulUsedSize) {
|
|
ac->ulTotalSize = ac->ulUsedSize;
|
|
}
|
|
|
|
if (ac->ulNeededSize < ac->ulNeededSize) {
|
|
ac->ulNeededSize = ac->ulUsedSize;
|
|
}
|
|
|
|
ac->ulLineDeviceID = TapiLine->ulDeviceID;
|
|
ac->ulAddressSharing = LINEADDRESSSHARING_PRIVATE;
|
|
ac->ulAddressStates = LINEADDRESSSTATE_NUMCALLS;
|
|
ac->ulCallInfoStates = LINECALLINFOSTATE_BEARERMODE |
|
|
LINECALLINFOSTATE_RATE |
|
|
LINECALLINFOSTATE_MEDIAMODE;
|
|
|
|
ac->ulCallStates = LINECALLSTATE_IDLE |
|
|
LINECALLSTATE_OFFERING |
|
|
LINECALLSTATE_ACCEPTED |
|
|
LINECALLSTATE_BUSY |
|
|
LINECALLSTATE_CONNECTED |
|
|
LINECALLSTATE_PROCEEDING |
|
|
LINECALLSTATE_DISCONNECTED;
|
|
|
|
ac->ulDialToneModes = 0;
|
|
ac->ulBusyModes = LINEBUSYMODE_UNAVAIL;
|
|
ac->ulSpecialInfo = 0;
|
|
|
|
ac->ulDisconnectModes = LINEDISCONNECTMODE_NORMAL |
|
|
LINEDISCONNECTMODE_BUSY |
|
|
LINEDISCONNECTMODE_NOANSWER;
|
|
|
|
TapiAddr->TapiLine = TapiLine;
|
|
TapiAddr->AddrId = AddrID;
|
|
|
|
PxFreeMem(EnumBuffer);
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Allocated TapiAddr %p AddrId %d for TapiLine %p\n", TapiAddr, TapiAddr->AddrId, TapiLine));
|
|
|
|
return (TapiAddr);
|
|
}
|
|
|
|
VOID
|
|
FreeTapiAddr(
|
|
PPX_TAPI_ADDR TapiAddr
|
|
)
|
|
{
|
|
//
|
|
// ToDo! we need to tear down all
|
|
// active calls on this address.
|
|
//
|
|
|
|
PxFreeMem(TapiAddr);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
AllocateTapiCallInfo(
|
|
PPX_VC pVc,
|
|
LINE_CALL_INFO UNALIGNED *LineCallInfo
|
|
)
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
ULONG SizeNeeded;
|
|
|
|
if (pVc->CallInfo) {
|
|
PxFreeMem(pVc->CallInfo);
|
|
}
|
|
|
|
if (LineCallInfo != NULL) {
|
|
SizeNeeded = LineCallInfo->ulUsedSize;
|
|
} else {
|
|
SizeNeeded = sizeof(LINE_CALL_INFO) + LINE_CALL_INFO_VAR_DATA_SIZE;
|
|
}
|
|
|
|
PxAllocMem(pVc->CallInfo, SizeNeeded, PX_LINECALLINFO_TAG);
|
|
|
|
if (pVc->CallInfo == NULL) {
|
|
return (NDIS_STATUS_RESOURCES);
|
|
}
|
|
|
|
pVc->ulCallInfoFieldsChanged = 0;
|
|
|
|
NdisZeroMemory(pVc->CallInfo, SizeNeeded);
|
|
|
|
if (LineCallInfo != NULL) {
|
|
NdisMoveMemory(pVc->CallInfo,
|
|
LineCallInfo,
|
|
LineCallInfo->ulUsedSize);
|
|
} else {
|
|
pVc->CallInfo->ulTotalSize = SizeNeeded;
|
|
pVc->CallInfo->ulNeededSize = SizeNeeded;
|
|
pVc->CallInfo->ulUsedSize = sizeof(LINE_CALL_INFO);
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
BOOLEAN
|
|
InsertVcInTable(
|
|
PPX_VC pVc
|
|
)
|
|
{
|
|
ULONG i;
|
|
ULONG index;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PUCHAR AllocatedMemory;
|
|
LOCK_STATE LockState;
|
|
PPX_CL_AF pClAf;
|
|
|
|
NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
|
|
|
|
if (VcTable.Count == VcTable.Size) {
|
|
ULONG SizeNeeded;
|
|
PUCHAR AllocatedMemory;
|
|
PPX_VC *NewTable;
|
|
|
|
//
|
|
// Grow the table
|
|
//
|
|
SizeNeeded =
|
|
(VcTable.Size + VcTable.Size/2) * sizeof(PPX_VC);
|
|
PxAllocMem(AllocatedMemory, SizeNeeded, PX_VCTABLE_TAG);
|
|
|
|
if (AllocatedMemory == NULL) {
|
|
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
|
|
return (FALSE);
|
|
}
|
|
|
|
RtlZeroMemory(AllocatedMemory,SizeNeeded);
|
|
|
|
NewTable = (PPX_VC*)AllocatedMemory;
|
|
|
|
RtlMoveMemory((PUCHAR)NewTable,
|
|
(PUCHAR)VcTable.Table,
|
|
(sizeof(PPX_VC) * VcTable.Size));
|
|
|
|
PxFreeMem(VcTable.Table);
|
|
|
|
VcTable.Table = NewTable;
|
|
VcTable.Size += VcTable.Size/2;
|
|
}
|
|
|
|
i = VcTable.Size;
|
|
index = VcTable.NextSlot;
|
|
|
|
do {
|
|
|
|
if (VcTable.Table[index] == NULL) {
|
|
|
|
NdisDprAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->hdCall = index;
|
|
|
|
VcTable.Table[index] = pVc;
|
|
InsertTailList(&VcTable.List,
|
|
&pVc->Linkage);
|
|
VcTable.Count++;
|
|
VcTable.NextSlot =
|
|
(VcTable.NextSlot + 1) % VcTable.Size;
|
|
|
|
pVc->Flags |= PX_VC_IN_TABLE;
|
|
pClAf = pVc->ClAf;
|
|
|
|
NdisDprReleaseSpinLock(&pVc->Lock);
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Inserting pVc %x in VcTable hdCall %d\n", pVc, pVc->hdCall));
|
|
break;
|
|
}
|
|
index = (index+1) % VcTable.Size;
|
|
|
|
} while (--i);
|
|
|
|
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
|
|
|
|
if (i != 0) {
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
REF_CL_AF(pClAf);
|
|
InsertTailList(&pClAf->VcList, &pVc->ClAfLinkage);
|
|
NdisReleaseSpinLock(&pClAf->Lock);
|
|
} else {
|
|
PXDEBUGP(PXD_TAPI,PXM_TAPI, ("Failed to insert pVc %x in VcTable\n", pVc));
|
|
}
|
|
|
|
return (i != 0);
|
|
}
|
|
|
|
VOID
|
|
RemoveVcFromTable(
|
|
PPX_VC pVc
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
PPX_CL_AF pClAf;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Removing pVc %x from VcTable hdCall %d\n", pVc, pVc->hdCall));
|
|
|
|
NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
|
|
|
|
ASSERT(VcTable.Table[pVc->hdCall] == pVc);
|
|
|
|
|
|
VcTable.Table[pVc->hdCall] = NULL;
|
|
|
|
VcTable.Count--;
|
|
|
|
NdisDprAcquireSpinLock(&pVc->Lock);
|
|
|
|
RemoveEntryList(&pVc->Linkage);
|
|
|
|
pVc->Flags &= ~PX_VC_IN_TABLE;
|
|
pClAf = pVc->ClAf;
|
|
|
|
NdisDprReleaseSpinLock(&pVc->Lock);
|
|
|
|
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
|
|
|
|
NdisAcquireSpinLock(&pClAf->Lock);
|
|
|
|
RemoveEntryList(&pVc->ClAfLinkage);
|
|
|
|
DEREF_CL_AF_LOCKED(pClAf);
|
|
}
|
|
|
|
BOOLEAN
|
|
IsTapiLineValid(
|
|
ULONG hdLine,
|
|
PPX_TAPI_LINE *TapiLine
|
|
)
|
|
{
|
|
PPX_TAPI_LINE RetLine;
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
*TapiLine = NULL;
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE RetLine;
|
|
|
|
RetLine = LineTable.Table[i];
|
|
|
|
if ((RetLine != NULL) &&
|
|
(RetLine->hdLine == hdLine)) {
|
|
*TapiLine = RetLine;
|
|
NdisDprAcquireSpinLock(&RetLine->Lock);
|
|
REF_TAPILINE(RetLine);
|
|
NdisDprReleaseSpinLock(&RetLine->Lock);
|
|
break;
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
|
|
return (*TapiLine != NULL);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
IsTapiDeviceValid(
|
|
ULONG ulDeviceID,
|
|
PPX_TAPI_LINE *TapiLine
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
*TapiLine = NULL;
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE RetLine;
|
|
|
|
RetLine = LineTable.Table[i];
|
|
|
|
if ((RetLine != NULL) &&
|
|
(RetLine->ulDeviceID == ulDeviceID)) {
|
|
*TapiLine = RetLine;
|
|
NdisDprAcquireSpinLock(&RetLine->Lock);
|
|
REF_TAPILINE(RetLine);
|
|
NdisDprReleaseSpinLock(&RetLine->Lock);
|
|
break;
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
|
|
return (*TapiLine != NULL);
|
|
}
|
|
|
|
BOOLEAN
|
|
IsVcValid(
|
|
ULONG_PTR CallId,
|
|
PPX_VC *pVc
|
|
)
|
|
{
|
|
PPX_VC RetVc = NULL;
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
|
|
|
|
|
|
if (CallId < VcTable.Size) {
|
|
RetVc = VcTable.Table[CallId];
|
|
}
|
|
|
|
if (RetVc != NULL) {
|
|
NdisDprAcquireSpinLock(&RetVc->Lock);
|
|
REF_VC(RetVc);
|
|
NdisDprReleaseSpinLock(&RetVc->Lock);
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
|
|
|
|
*pVc = RetVc;
|
|
|
|
return (RetVc != NULL);
|
|
}
|
|
|
|
VOID
|
|
GetVcFromCtx(
|
|
NDIS_HANDLE VcCtx,
|
|
PPX_VC *pVc
|
|
)
|
|
{
|
|
PPX_VC RetVc = NULL;
|
|
ULONG_PTR i;
|
|
LOCK_STATE LockState;
|
|
|
|
NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
|
|
|
|
i = (ULONG_PTR)(VcCtx);
|
|
|
|
if (i < VcTable.Size) {
|
|
RetVc = VcTable.Table[i];
|
|
}
|
|
|
|
if (RetVc != NULL) {
|
|
NdisDprAcquireSpinLock(&RetVc->Lock);
|
|
REF_VC(RetVc);
|
|
NdisDprReleaseSpinLock(&RetVc->Lock);
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
|
|
|
|
*pVc = RetVc;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Function assumes that the TapiLine's spinlock is held!
|
|
//
|
|
BOOLEAN
|
|
IsAddressValid(
|
|
PPX_TAPI_LINE TapiLine,
|
|
ULONG AddressId,
|
|
PPX_TAPI_ADDR *TapiAddr
|
|
)
|
|
{
|
|
PPX_TAPI_ADDR RetAddr = NULL;
|
|
|
|
do {
|
|
|
|
if (AddressId >= TapiLine->AddrTable.Count) {
|
|
break;
|
|
}
|
|
|
|
RetAddr = TapiLine->AddrTable.Table[AddressId];
|
|
|
|
} while (FALSE);
|
|
|
|
*TapiAddr = RetAddr;
|
|
|
|
return (RetAddr != NULL);
|
|
}
|
|
|
|
BOOLEAN
|
|
GetLineFromCmLineID(
|
|
PPX_TAPI_PROVIDER TapiProvider,
|
|
ULONG CmLineID,
|
|
PPX_TAPI_LINE *TapiLine
|
|
)
|
|
{
|
|
PPX_TAPI_LINE RetLine;
|
|
|
|
NdisAcquireSpinLock(&TapiProvider->Lock);
|
|
|
|
RetLine = (PPX_TAPI_LINE)
|
|
TapiProvider->LineList.Flink;
|
|
|
|
while ((PVOID)RetLine != (PVOID)&TapiProvider->LineList) {
|
|
|
|
if ((RetLine->CmLineID == CmLineID) &&
|
|
(RetLine->DevStatus->ulNumOpens != 0)) {
|
|
break;
|
|
}
|
|
|
|
RetLine = (PPX_TAPI_LINE)
|
|
RetLine->Linkage.Flink;
|
|
}
|
|
|
|
if ((PVOID)RetLine == (PVOID)&TapiProvider->LineList) {
|
|
RetLine = NULL;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TapiProvider->Lock);
|
|
|
|
*TapiLine = RetLine;
|
|
|
|
return (RetLine != NULL);
|
|
}
|
|
|
|
BOOLEAN
|
|
GetAvailLineFromProvider(
|
|
PPX_TAPI_PROVIDER TapiProvider,
|
|
PPX_TAPI_LINE *TapiLine,
|
|
PPX_TAPI_ADDR *TapiAddr
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
PPX_TAPI_LINE tl;
|
|
|
|
NdisAcquireSpinLock(&TapiProvider->Lock);
|
|
|
|
tl = (PPX_TAPI_LINE)TapiProvider->LineList.Flink;
|
|
|
|
while ((PVOID)tl != (PVOID)&TapiProvider->LineList) {
|
|
PTAPI_ADDR_TABLE AddrTable;
|
|
PPX_TAPI_ADDR ta;
|
|
|
|
NdisDprAcquireSpinLock(&tl->Lock);
|
|
|
|
if (tl->DevStatus->ulNumOpens != 0) {
|
|
|
|
AddrTable = &tl->AddrTable;
|
|
ta = (PPX_TAPI_ADDR)AddrTable->List.Flink;
|
|
|
|
//
|
|
// Walk the addresses on this line
|
|
//
|
|
while ((PVOID)ta != (PVOID)&AddrTable->List) {
|
|
|
|
//
|
|
// If this address has a callcount that is
|
|
// < then the max num it supports, add another
|
|
// call on this address!
|
|
//
|
|
if (ta->CallCount < ta->Caps->ulMaxNumActiveCalls) {
|
|
|
|
*TapiLine = tl;
|
|
*TapiAddr = ta;
|
|
|
|
NdisDprReleaseSpinLock(&tl->Lock);
|
|
|
|
NdisReleaseSpinLock(&TapiProvider->Lock);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
ta = (PPX_TAPI_ADDR)ta->Linkage.Flink;
|
|
}
|
|
}
|
|
|
|
NdisDprReleaseSpinLock(&tl->Lock);
|
|
|
|
tl = (PPX_TAPI_LINE)tl->Linkage.Flink;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TapiProvider->Lock);
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Function assumes that the TapiLine's spinlock is held!
|
|
//
|
|
PPX_TAPI_ADDR
|
|
GetAvailAddrFromLine(
|
|
PPX_TAPI_LINE TapiLine
|
|
)
|
|
{
|
|
PPX_TAPI_ADDR TapiAddr;
|
|
PTAPI_ADDR_TABLE AddrTable;
|
|
|
|
AddrTable = &TapiLine->AddrTable;
|
|
TapiAddr = (PPX_TAPI_ADDR)AddrTable->List.Flink;
|
|
|
|
//
|
|
// Walk the addresses on this line
|
|
//
|
|
while ((PVOID)TapiAddr != (PVOID)&AddrTable->List) {
|
|
|
|
//
|
|
// If this address has a callcount that is
|
|
// < then the max num it supports, add another
|
|
// call on this address!
|
|
//
|
|
if (TapiAddr->CallCount <
|
|
TapiAddr->Caps->ulMaxNumActiveCalls) {
|
|
|
|
return (TapiAddr);
|
|
}
|
|
|
|
TapiAddr = (PPX_TAPI_ADDR)TapiAddr->Linkage.Flink;
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
BOOLEAN
|
|
InsertLineInTable(
|
|
PPX_TAPI_LINE TapiLine
|
|
)
|
|
{
|
|
ULONG i;
|
|
ULONG index;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PUCHAR AllocatedMemory;
|
|
LOCK_STATE LockState;
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
|
|
|
|
if (LineTable.Count == LineTable.Size) {
|
|
ULONG SizeNeeded;
|
|
PUCHAR AllocatedMemory;
|
|
PPX_TAPI_LINE *NewTable;
|
|
|
|
//
|
|
// Grow the table
|
|
//
|
|
SizeNeeded =
|
|
(LineTable.Size + LineTable.Size/2) * sizeof(PPX_TAPI_LINE);
|
|
PxAllocMem(AllocatedMemory, SizeNeeded, PX_LINETABLE_TAG);
|
|
|
|
if (AllocatedMemory == NULL) {
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
return (FALSE);
|
|
}
|
|
|
|
RtlZeroMemory(AllocatedMemory,SizeNeeded);
|
|
|
|
NewTable = (PPX_TAPI_LINE*)AllocatedMemory;
|
|
|
|
RtlMoveMemory((PUCHAR)NewTable,
|
|
(PUCHAR)LineTable.Table,
|
|
(sizeof(PPX_TAPI_LINE) * LineTable.Size));
|
|
|
|
PxFreeMem(LineTable.Table);
|
|
|
|
LineTable.Table = NewTable;
|
|
LineTable.Size += LineTable.Size/2;
|
|
}
|
|
|
|
i = LineTable.Size;
|
|
index = LineTable.NextSlot;
|
|
|
|
do {
|
|
|
|
if (LineTable.Table[index] == NULL) {
|
|
|
|
TapiLine->hdLine = index;
|
|
TapiLine->Flags |= PX_LINE_IN_TABLE;
|
|
LineTable.Table[index] = TapiLine;
|
|
LineTable.Count++;
|
|
LineTable.NextSlot =
|
|
(LineTable.NextSlot + 1) % LineTable.Size;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("Inserting TapiLine %p in LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
|
|
break;
|
|
}
|
|
index = (index+1) % LineTable.Size;
|
|
|
|
} while (--i);
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
|
|
#if DBG
|
|
if (i == 0) {
|
|
PXDEBUGP(PXD_TAPI,PXM_TAPI,
|
|
("Failed to insert TapiLine %p in LineTable\n", TapiLine));
|
|
}
|
|
#endif
|
|
|
|
return (i != 0);
|
|
}
|
|
|
|
VOID
|
|
RemoveTapiLineFromTable(
|
|
PPX_TAPI_LINE TapiLine
|
|
)
|
|
{
|
|
LOCK_STATE LockState;
|
|
|
|
PXDEBUGP(PXD_TAPI, PXM_TAPI,
|
|
("Removing TapiLine %p from LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
|
|
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
|
|
|
|
ASSERT(LineTable.Table[TapiLine->hdLine] == TapiLine);
|
|
|
|
LineTable.Table[TapiLine->hdLine] = NULL;
|
|
|
|
TapiLine->Flags &= ~PX_LINE_IN_TABLE;
|
|
|
|
LineTable.Count--;
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PxVcCleanup(
|
|
PPX_VC pVc,
|
|
ULONG Flags
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_TAPI,
|
|
("PxVcCleanup: Vc %p, State: %x, HandoffState: %x VcFlags: %x, NewFlags: %x\n",
|
|
pVc, pVc->State, pVc->HandoffState, Flags, pVc->Flags, Flags));
|
|
|
|
//
|
|
// Terminate Digit Gathering or Monitoring.
|
|
//
|
|
|
|
if (pVc->ulMonitorDigitsModes != 0) {
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
PxStopDigitReporting(pVc);
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
pVc->ulMonitorDigitsModes = 0;
|
|
} else if (pVc->PendingGatherDigits != NULL) {
|
|
PNDISTAPI_REQUEST pNdisTapiRequest = pVc->PendingGatherDigits;
|
|
|
|
pVc->PendingGatherDigits = NULL;
|
|
PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
|
|
}
|
|
|
|
switch (pVc->State) {
|
|
case PX_VC_IDLE:
|
|
//
|
|
// Already idle do nothing.
|
|
//
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
|
|
case PX_VC_PROCEEDING:
|
|
//
|
|
// We have an outgoing call, when it completes close
|
|
// it down with ndis and complete the drop when
|
|
// in PxClCloseCallComplete.
|
|
//
|
|
pVc->PrevState = pVc->State;
|
|
pVc->State = PX_VC_DISCONNECTING;
|
|
|
|
//
|
|
// Attempt to close the call directly
|
|
// if this fails we will cleanup when
|
|
// the outgoing call completes
|
|
//
|
|
pVc->Flags |= (PX_VC_OUTCALL_ABORTING |
|
|
PX_VC_CLEANUP_CM |
|
|
Flags);
|
|
|
|
PxCloseCallWithCm(pVc);
|
|
|
|
Status = NDIS_STATUS_PENDING;
|
|
break;
|
|
|
|
case PX_VC_OFFERING:
|
|
//
|
|
// We have an incoming call offered to tapi. Close
|
|
// it down now by calling it's callcomplete handler
|
|
// with a non-success value.
|
|
//
|
|
pVc->Flags |= (Flags |
|
|
PX_VC_INCALL_ABORTING);
|
|
|
|
pVc->PrevState = pVc->State;
|
|
|
|
if (pVc->Flags & PX_VC_CLEANUP_CM) {
|
|
pVc->State= PX_VC_DISCONNECTING;
|
|
} else {
|
|
pVc->State = PX_VC_IDLE;
|
|
}
|
|
|
|
if (pVc->Flags & PX_VC_CALLTIMER_STARTED) {
|
|
PxStopIncomingCallTimeout(pVc);
|
|
}
|
|
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
NdisClIncomingCallComplete(NDIS_STATUS_FAILURE,
|
|
pVc->ClVcHandle,
|
|
pVc->pCallParameters);
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
if (pVc->Flags & PX_VC_CLEANUP_CM) {
|
|
|
|
PxCloseCallWithCm(pVc);
|
|
|
|
} else {
|
|
SendTapiCallState(pVc,
|
|
LINECALLSTATE_DISCONNECTED,
|
|
0,
|
|
pVc->CallInfo->ulMediaMode);
|
|
|
|
//
|
|
// Remove the ref applied in PxClIncomingCall.
|
|
// Don't use the full deref code here as the
|
|
// ref applied when we mapped the vc will
|
|
// keep the vc around.
|
|
//
|
|
pVc->RefCount--;
|
|
}
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
break;
|
|
|
|
case PX_VC_DISCONNECTING:
|
|
pVc->Flags |= (Flags);
|
|
Status = NDIS_STATUS_PENDING;
|
|
break;
|
|
|
|
case PX_VC_CONNECTED:
|
|
//
|
|
// We have a call that needs to be closed with ndis.
|
|
// This may include dropping the call with a client
|
|
// depending on the handoff state. Complete the drop
|
|
// irp in PxClCloseCallComplete
|
|
//
|
|
if (!(pVc->Flags & PX_VC_DROP_PENDING)) {
|
|
|
|
pVc->PrevState = pVc->State;
|
|
pVc->State = PX_VC_DISCONNECTING;
|
|
|
|
pVc->Flags |= (Flags | PX_VC_CLEANUP_CM);
|
|
|
|
Status =
|
|
PxCloseCallWithCl(pVc);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
PxCloseCallWithCm(pVc);
|
|
}
|
|
}
|
|
|
|
Status = NDIS_STATUS_PENDING;
|
|
|
|
break;
|
|
|
|
default:
|
|
PXDEBUGP(PXD_FATAL, PXM_TAPI,
|
|
("PxVcCleanup: Invalid VcState! Vc: %p VcState: %x CallState: %x\n",
|
|
pVc, pVc->State, pVc->ulCallState ));
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|