4929 lines
137 KiB
C
4929 lines
137 KiB
C
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Module Name:
|
||
|
||
tapi.c
|
||
|
||
Abstract:
|
||
|
||
This module contains all the TAPI_OID processing routines.
|
||
|
||
Author:
|
||
|
||
Hakan Berk - Microsoft, Inc. (hakanb@microsoft.com) Feb-2000
|
||
|
||
Environment:
|
||
|
||
Windows 2000 kernel mode Miniport driver or equivalent.
|
||
|
||
Revision History:
|
||
|
||
---------------------------------------------------------------------------*/
|
||
|
||
#include <ntddk.h>
|
||
#include <ntddndis.h>
|
||
#include <ndis.h>
|
||
#include <ndiswan.h>
|
||
#include <ndistapi.h>
|
||
#include <ntverp.h>
|
||
|
||
#include "debug.h"
|
||
#include "timer.h"
|
||
#include "bpool.h"
|
||
#include "ppool.h"
|
||
#include "util.h"
|
||
#include "packet.h"
|
||
#include "protocol.h"
|
||
#include "miniport.h"
|
||
#include "tapi.h"
|
||
#include "fsm.h"
|
||
|
||
extern TIMERQ gl_TimerQ;
|
||
|
||
extern NPAGED_LOOKASIDE_LIST gl_llistWorkItems;
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// Tapi provider, line and call context functions
|
||
//
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
|
||
VOID
|
||
ReferenceCall(
|
||
IN CALL* pCall,
|
||
IN BOOLEAN fAcquireLock
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will increment the reference count on the call object.
|
||
|
||
CAUTION: If fAcquireLock is set, this function will acquire the lock for the
|
||
call, otherwise it will assume the caller owns the lock.
|
||
|
||
Parameters:
|
||
|
||
pCall _ A pointer to our call information structure.
|
||
|
||
fAcquireLock _ Indicates if the caller already has the lock or not.
|
||
Caller must set this flag to FALSE if it has the lock,
|
||
otherwise it must be supplied as TRUE.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
LONG lRef;
|
||
|
||
TRACE( TL_V, TM_Tp, ("+ReferenceCall") );
|
||
|
||
if ( fAcquireLock )
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
lRef = ++pCall->lRef;
|
||
|
||
if ( fAcquireLock )
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
TRACE( TL_V, TM_Tp, ("-ReferenceCall=$%d",lRef) );
|
||
}
|
||
|
||
VOID
|
||
DereferenceCall(
|
||
IN CALL *pCall
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will decrement the reference count on the call object
|
||
|
||
If ref count drops to 0 (which means the call has been closed),
|
||
it will set the CLBF_CallClosed bit. Then it will call TpCloseCallComplete()
|
||
function which eventually handles destroying the resources allocated for
|
||
this call context.
|
||
|
||
CAUTION: All locks must be released before calling this function because
|
||
it may cause a set of cascading events.
|
||
|
||
Parameters:
|
||
|
||
pCall _ A pointer ot our call information structure.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
BOOLEAN fCallTpCloseCallComplete = FALSE;
|
||
LONG lRef;
|
||
|
||
TRACE( TL_V, TM_Tp, ("+DereferenceCall") );
|
||
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
lRef = --pCall->lRef;
|
||
|
||
if ( lRef == 0 )
|
||
{
|
||
pCall->ulClFlags &= ~CLBF_CallOpen;
|
||
pCall->ulClFlags &= ~CLBF_CallClosePending;
|
||
pCall->ulClFlags |= CLBF_CallClosed;
|
||
|
||
fCallTpCloseCallComplete = TRUE;
|
||
}
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
if ( fCallTpCloseCallComplete )
|
||
TpCloseCallComplete( pCall );
|
||
|
||
TRACE( TL_V, TM_Tp, ("-DereferenceCall=$%d",lRef) );
|
||
}
|
||
|
||
|
||
VOID
|
||
ReferenceLine(
|
||
IN LINE* pLine,
|
||
IN BOOLEAN fAcquireLock
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will increment the reference count on the line object.
|
||
|
||
CAUTION: If fAcquireLock is set, this function will acquire the lock for the
|
||
line, otherwise it will assume the caller owns the lock.
|
||
|
||
Parameters:
|
||
|
||
pLine _ A pointer to our line information structure.
|
||
|
||
fAcquireLock _ Indicates if the caller already has the lock or not.
|
||
Caller must set this flag to FALSE if it has the lock,
|
||
otherwise it must be supplied as TRUE.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
LONG lRef;
|
||
|
||
TRACE( TL_V, TM_Tp, ("+ReferenceLine") );
|
||
|
||
if ( fAcquireLock )
|
||
NdisAcquireSpinLock( &pLine->lockLine );
|
||
|
||
lRef = ++pLine->lRef;
|
||
|
||
if ( fAcquireLock )
|
||
NdisReleaseSpinLock( &pLine->lockLine );
|
||
|
||
TRACE( TL_V, TM_Tp, ("-ReferenceLine=$%d",lRef) );
|
||
|
||
}
|
||
|
||
VOID
|
||
DereferenceLine(
|
||
IN LINE *pLine
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will decrement the reference count on the line object
|
||
|
||
If the ref count drops to 0 (which means the line has been closed),
|
||
it will set the LNBF_CallClosed bit. Then it will call TpCloseLineComplete()
|
||
function which eventually handles destroying the resources allocated for
|
||
this line context.
|
||
|
||
CAUTION: All locks must be released before calling this function because
|
||
it may cause a set of cascading events.
|
||
|
||
Parameters:
|
||
|
||
pLine _ A pointer to our line information structure.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
BOOLEAN fCallTpCloseLineComplete = FALSE;
|
||
LONG lRef;
|
||
|
||
TRACE( TL_V, TM_Tp, ("+DereferenceLine") );
|
||
|
||
|
||
NdisAcquireSpinLock( &pLine->lockLine );
|
||
|
||
lRef = --pLine->lRef;
|
||
|
||
if ( lRef == 0 )
|
||
{
|
||
pLine->ulLnFlags &= ~LNBF_LineOpen;
|
||
pLine->ulLnFlags &= ~LNBF_LineClosePending;
|
||
pLine->ulLnFlags |= LNBF_LineClosed;
|
||
|
||
fCallTpCloseLineComplete = TRUE;
|
||
}
|
||
|
||
NdisReleaseSpinLock( &pLine->lockLine );
|
||
|
||
if ( fCallTpCloseLineComplete )
|
||
TpCloseLineComplete( pLine );
|
||
|
||
TRACE( TL_V, TM_Tp, ("-DereferenceLine=$%d",lRef) );
|
||
}
|
||
|
||
VOID
|
||
ReferenceTapiProv(
|
||
IN ADAPTER* pAdapter,
|
||
IN BOOLEAN fAcquireLock
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will increment the reference count on the tapi prov object.
|
||
|
||
CAUTION: If fAcquireLock is set, this function will acquire the lock for the
|
||
line, otherwise it will assume the caller owns the lock.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
fAcquireLock _ Indicates if the caller already has the lock or not.
|
||
Caller must set this flag to FALSE if it has the lock,
|
||
otherwise it must be supplied as TRUE.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
LONG lRef;
|
||
|
||
TRACE( TL_V, TM_Tp, ("+ReferenceTapiProv") );
|
||
|
||
if ( fAcquireLock )
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
lRef = ++pAdapter->TapiProv.lRef;
|
||
|
||
if ( fAcquireLock )
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
TRACE( TL_V, TM_Tp, ("-ReferenceTapiProv=$%d",lRef) );
|
||
}
|
||
|
||
|
||
VOID
|
||
DereferenceTapiProv(
|
||
IN ADAPTER *pAdapter
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will decrement the reference count on the tapi prov object
|
||
|
||
CAUTION: All locks must be released before calling this function because
|
||
it may cause a set of cascading events.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter line information structure.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
BOOLEAN fCallTpProviderShutdownComplete = FALSE;
|
||
LONG lRef;
|
||
|
||
TRACE( TL_V, TM_Tp, ("+DereferenceTapiProv") );
|
||
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
lRef = --pAdapter->TapiProv.lRef;
|
||
|
||
if ( lRef == 0 )
|
||
{
|
||
pAdapter->TapiProv.ulTpFlags &= ~TPBF_TapiProvInitialized;
|
||
pAdapter->TapiProv.ulTpFlags &= ~TPBF_TapiProvShutdownPending;
|
||
pAdapter->TapiProv.ulTpFlags |= TPBF_TapiProvShutdown;
|
||
|
||
fCallTpProviderShutdownComplete = TRUE;
|
||
}
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
if ( fCallTpProviderShutdownComplete )
|
||
TpProviderShutdownComplete( pAdapter );
|
||
|
||
TRACE( TL_V, TM_Tp, ("-DereferenceTapiProv=$%d",lRef) );
|
||
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpProviderInitialize(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_PROVIDER_INITIALIZE pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request initializes the TAPI portion of the miniport.
|
||
|
||
It will set Tapi Provider's state to initialize, and reference both the
|
||
owning adapter and tapi provider.
|
||
|
||
Parameters:
|
||
|
||
Adapter _ A pointer ot our adapter information structure.
|
||
|
||
Request _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_PROVIDER_INITIALIZE
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN ULONG ulDeviceIDBase;
|
||
OUT ULONG ulNumLineDevs;
|
||
OUT ULONG ulProviderID;
|
||
|
||
} NDIS_TAPI_PROVIDER_INITIALIZE, *PNDIS_TAPI_PROVIDER_INITIALIZE;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_STATUS status = NDIS_STATUS_RESOURCES;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpProviderInitialize") );
|
||
|
||
do
|
||
{
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpProviderInitialize: Invalid parameter") );
|
||
|
||
status = NDIS_STATUS_TAPI_INVALPARAM;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Initialize the tapi provider context
|
||
//
|
||
NdisZeroMemory( &pAdapter->TapiProv, sizeof( pAdapter->TapiProv ) );
|
||
|
||
//
|
||
// Try to allocate resources
|
||
//
|
||
NdisAllocateMemoryWithTag( (PVOID) &pAdapter->TapiProv.LineTable,
|
||
sizeof( LINE* ) * pAdapter->nMaxLines,
|
||
MTAG_TAPIPROV );
|
||
|
||
if ( pAdapter->TapiProv.LineTable == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpProviderInitialize: Could not allocate line table") );
|
||
|
||
break;
|
||
}
|
||
|
||
NdisZeroMemory( pAdapter->TapiProv.LineTable, sizeof( LINE* ) * pAdapter->nMaxLines );
|
||
|
||
pAdapter->TapiProv.hCallTable = InitializeHandleTable( pAdapter->nMaxLines * pAdapter->nCallsPerLine );
|
||
|
||
if ( pAdapter->TapiProv.hCallTable == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpProviderInitialize: Could not allocate call handle table") );
|
||
|
||
break;
|
||
}
|
||
|
||
pAdapter->TapiProv.ulTpFlags = TPBF_TapiProvInitialized;
|
||
|
||
pAdapter->TapiProv.ulDeviceIDBase = pRequest->ulDeviceIDBase;
|
||
|
||
//
|
||
// Do referencing
|
||
//
|
||
ReferenceTapiProv( pAdapter, FALSE );
|
||
|
||
ReferenceAdapter( pAdapter, TRUE );
|
||
|
||
status = NDIS_STATUS_SUCCESS;
|
||
|
||
} while ( FALSE );
|
||
|
||
if ( status == NDIS_STATUS_SUCCESS )
|
||
{
|
||
//
|
||
// Set output information
|
||
//
|
||
pRequest->ulNumLineDevs = pAdapter->nMaxLines;
|
||
|
||
pRequest->ulProviderID = (ULONG_PTR) pAdapter->MiniportAdapterHandle;
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Somethings failed, clean up
|
||
//
|
||
TpProviderCleanup( pAdapter );
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpProviderInitialize=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpProviderShutdown(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_PROVIDER_SHUTDOWN pRequest,
|
||
IN BOOLEAN fNotifyNDIS
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request shuts down the miniport. The miniport should terminate any
|
||
activities it has in progress.
|
||
|
||
This operation might pend as there might be lines and call contexts still
|
||
active. So this function marks the tapi provider context as close pending
|
||
and calls TpCloseLine() on all active calls, and removes the reference added
|
||
on the tapi provider in TpProviderInitialize().
|
||
|
||
When ref count on the tapi provider context reaches 0, TpProviderShutdownComplete()
|
||
will be called to clean up the tapi provider context, and remove the reference
|
||
on the owning adapter.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
If supplied as NULL, then we do not need to notify NDIS.
|
||
|
||
typedef struct _NDIS_TAPI_PROVIDER_SHUTDOWN
|
||
{
|
||
IN ULONG ulRequestID;
|
||
|
||
} NDIS_TAPI_PROVIDER_SHUTDOWN, *PNDIS_TAPI_PROVIDER_SHUTDOWN;
|
||
|
||
|
||
fNotifyNDIS _ Indicates if NDIS needs to be notified about the completion
|
||
of this operation
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS:
|
||
Tapi provider shutdown and cleaned up succesfully.
|
||
|
||
NDIS_STATUS_PENDING
|
||
Shutdown operation is pending. When all shutdown operation completes
|
||
owning adapter context will be dereferenced.
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_STATUS status;
|
||
BOOLEAN fDereferenceTapiProv = FALSE;
|
||
BOOLEAN fLockAcquired = FALSE;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpProviderShutdown") );
|
||
|
||
do
|
||
{
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpProviderShutdown: Invalid parameter") );
|
||
|
||
status = NDIS_STATUS_TAPI_INVALPARAM;
|
||
|
||
break;
|
||
}
|
||
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
fLockAcquired = TRUE;
|
||
|
||
//
|
||
// See if tapi provider was initialized at all
|
||
//
|
||
if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
|
||
{
|
||
//
|
||
// Tapi provider was not initialized so just return
|
||
//
|
||
status = NDIS_STATUS_SUCCESS;
|
||
|
||
break;
|
||
}
|
||
|
||
|
||
//
|
||
// See if we can shutdown immediately
|
||
//
|
||
if ( pAdapter->TapiProv.lRef == 1 )
|
||
{
|
||
//
|
||
// We are holding the only reference, so we can shutdown immediately
|
||
//
|
||
pAdapter->TapiProv.ulTpFlags &= ~TPBF_TapiProvInitialized;
|
||
|
||
pAdapter->TapiProv.ulTpFlags |= TPBF_TapiProvShutdown;
|
||
|
||
status = NDIS_STATUS_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
UINT i;
|
||
|
||
//
|
||
// Mark Tapi provider as shutdown pending
|
||
//
|
||
pAdapter->TapiProv.ulTpFlags |= TPBF_TapiProvShutdownPending;
|
||
|
||
//
|
||
// Mark tapi prov if the result of this operation needs to be reported to NDIS
|
||
//
|
||
if ( fNotifyNDIS )
|
||
pAdapter->TapiProv.ulTpFlags |= TPBF_NotifyNDIS;
|
||
|
||
//
|
||
// Close all active lines
|
||
//
|
||
for ( i = 0; i < pAdapter->nMaxLines; i++)
|
||
{
|
||
NDIS_TAPI_CLOSE DummyRequest;
|
||
|
||
LINE* pLine = (LINE*) pAdapter->TapiProv.LineTable[i];
|
||
|
||
if ( pLine )
|
||
{
|
||
|
||
DummyRequest.hdLine = pLine->hdLine;
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
TpCloseLine( pAdapter, &DummyRequest, FALSE );
|
||
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
}
|
||
|
||
}
|
||
|
||
status = NDIS_STATUS_PENDING;
|
||
}
|
||
|
||
fDereferenceTapiProv = TRUE;
|
||
|
||
} while ( FALSE );
|
||
|
||
if ( fLockAcquired )
|
||
{
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
}
|
||
|
||
if ( fDereferenceTapiProv )
|
||
{
|
||
DereferenceTapiProv( pAdapter );
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpProviderShutdown=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
#define INVALID_LINE_HANDLE (HDRV_LINE) -1
|
||
|
||
HDRV_LINE
|
||
TpGetHdLineFromDeviceId(
|
||
ADAPTER* pAdapter,
|
||
ULONG ulID
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function is used to map a Tapi Device Id to the driver's line handle.
|
||
It returns INVALID_LINE_HANDLE if it can not map the device id.
|
||
|
||
REMARK:
|
||
- pAdapter must not be NULL.
|
||
- It must be called from one of the Tp...OidHandler() functions since
|
||
this function relies on this and assumes there won't be any
|
||
synchronization problems.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
uldID _ Device Id that identifies a line context
|
||
|
||
Return Values:
|
||
|
||
Handle to the line context if device id can be mapped to a valid line context,
|
||
and INVALID_LINE_HANDLE otherwise.
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvShutdownPending ) &&
|
||
( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
|
||
{
|
||
if ( ( ulID < ( pAdapter->TapiProv.ulDeviceIDBase + pAdapter->nMaxLines ) ) &&
|
||
( ulID >= pAdapter->TapiProv.ulDeviceIDBase ) )
|
||
{
|
||
return (HDRV_LINE) ( ulID - pAdapter->TapiProv.ulDeviceIDBase );
|
||
}
|
||
}
|
||
|
||
return INVALID_LINE_HANDLE;
|
||
}
|
||
|
||
LINE*
|
||
TpGetLinePtrFromHdLineEx(
|
||
ADAPTER* pAdapter,
|
||
HDRV_LINE hdLine
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function is used to map a driver line handle to the line context ptr.
|
||
It returns NULL if it can not map the handle. This is exactly the same as
|
||
TpGetLinePtrFromHdLine function except that it doesn't check for the
|
||
shutdown state.
|
||
|
||
REMARK:
|
||
- pAdapter must not be NULL.
|
||
- It must be called from one of the Tp...OidHandler() functions since
|
||
this function relies on this and assumes there won't be any
|
||
synchronization problems.
|
||
(Basically assumes pAdapter->lock is being held)
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
hdL _ Driver's line handle
|
||
|
||
Return Values:
|
||
|
||
Pointer to the Line context associated with the Line handle provided
|
||
if mapping is succesful, and NULL otherwise.
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
if ( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized )
|
||
{
|
||
if ( ( (ULONG) hdLine < (ULONG) pAdapter->nMaxLines ) )
|
||
{
|
||
ASSERT( pAdapter->TapiProv.LineTable != 0 );
|
||
|
||
return pAdapter->TapiProv.LineTable[ (ULONG) hdLine ];
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
LINE*
|
||
TpGetLinePtrFromHdLine(
|
||
ADAPTER* pAdapter,
|
||
HDRV_LINE hdLine
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function is used to map a driver line handle to the line context ptr.
|
||
It returns NULL if it can not map the handle.
|
||
|
||
REMARK:
|
||
- pAdapter must not be NULL.
|
||
- It must be called from one of the Tp...OidHandler() functions since
|
||
this function relies on this and assumes there won't be any
|
||
synchronization problems.
|
||
(Basically assumes pAdapter->lock is being held)
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
hdL _ Driver's line handle
|
||
|
||
Return Values:
|
||
|
||
Pointer to the Line context associated with the Line handle provided
|
||
if mapping is succesful, and NULL otherwise.
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvShutdownPending ) &&
|
||
( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
|
||
{
|
||
if ( ( (ULONG) hdLine < (ULONG) pAdapter->nMaxLines ) )
|
||
{
|
||
ASSERT( pAdapter->TapiProv.LineTable != 0 );
|
||
|
||
return pAdapter->TapiProv.LineTable[ (ULONG) hdLine ];
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
NDIS_STATUS
|
||
TpOpenLine(
|
||
ADAPTER* pAdapter,
|
||
PNDIS_TAPI_OPEN pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function opens the line device whose device ID is given, returning
|
||
the miniport<72>s handle for the device. The miniport must retain the
|
||
Connection Wrapper's handle for the device for use in subsequent calls to
|
||
the LINE_EVENT callback procedure.
|
||
|
||
hdLine returned is the index to the pAdapter->TapiProv.LineTable array
|
||
that holds the pointer to the new line context.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
pRequest - A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_OPEN
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN ULONG ulDeviceID;
|
||
IN HTAPI_LINE htLine;
|
||
OUT HDRV_LINE hdLine;
|
||
|
||
} NDIS_TAPI_OPEN, *PNDIS_TAPI_OPEN;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_PENDING
|
||
NDIS_STATUS_TAPI_ALLOCATED
|
||
NDIS_STATUS_TAPI_INVALMEDIAMODE
|
||
NDIS_STATUS_FAILURE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_STATUS status = NDIS_STATUS_FAILURE;
|
||
HDRV_LINE hdLine = INVALID_LINE_HANDLE;
|
||
LINE* pLine = NULL;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpOpenLine") );
|
||
|
||
do
|
||
{
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpOpenLine: Invalid parameter") );
|
||
|
||
status = NDIS_STATUS_TAPI_INVALPARAM;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Map the device id to an entry in our line table
|
||
//
|
||
hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
|
||
|
||
if ( hdLine == INVALID_LINE_HANDLE )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpOpenLine: Invalid handle supplied") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Make sure the line is not busy already
|
||
//
|
||
if ( TpGetLinePtrFromHdLine( pAdapter, hdLine ) != NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpOpenLine: Line is busy") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Allocate the line context
|
||
//
|
||
if ( ALLOC_LINE( &pLine ) != NDIS_STATUS_SUCCESS )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpOpenLine: Could not allocate context") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Initialize line context
|
||
//
|
||
NdisZeroMemory( pLine, sizeof( LINE ) );
|
||
|
||
pLine->tagLine = MTAG_LINE;
|
||
|
||
NdisAllocateSpinLock( &pLine->lockLine );
|
||
|
||
pLine->ulLnFlags = LNBF_LineOpen;
|
||
|
||
if ( pAdapter->fClientRole )
|
||
{
|
||
pLine->ulLnFlags |= LNBF_MakeOutgoingCalls;
|
||
}
|
||
|
||
//
|
||
// Copy related info from adapter context
|
||
//
|
||
pLine->pAdapter = pAdapter;
|
||
|
||
pLine->nMaxCalls = pAdapter->nCallsPerLine;
|
||
|
||
InitializeListHead( &pLine->linkCalls );
|
||
|
||
//
|
||
// Set tapi handles
|
||
//
|
||
pLine->htLine = pRequest->htLine;
|
||
|
||
pLine->hdLine = hdLine;
|
||
|
||
//
|
||
// Insert new line context to line table of tapi provider
|
||
//
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
pAdapter->TapiProv.LineTable[ (ULONG) hdLine ] = pLine;
|
||
|
||
pAdapter->TapiProv.nActiveLines++;
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
//
|
||
// Do referencing
|
||
//
|
||
ReferenceLine( pLine, FALSE );
|
||
|
||
ReferenceTapiProv( pAdapter, TRUE );
|
||
|
||
status = NDIS_STATUS_SUCCESS;
|
||
|
||
} while ( FALSE );
|
||
|
||
if ( status == NDIS_STATUS_SUCCESS )
|
||
{
|
||
pRequest->hdLine = hdLine;
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpOpenLine=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpCloseLine(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_CLOSE pRequest,
|
||
IN BOOLEAN fNotifyNDIS
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request closes the specified open line device after completing or
|
||
aborting all outstanding calls and asynchronous requests on the device.
|
||
|
||
It will remove the reference on the line context added in TpOpenLine().
|
||
|
||
It will be called from 2 places:
|
||
1. When miniport receives an OID_TAPI_CLOSE.
|
||
In this case, fNotifyNDIS will be set as TRUE.
|
||
|
||
2. When miniport is halting, TpProviderShutdown() will call
|
||
this function for every active line context.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_CLOSE
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_LINE hdLine;
|
||
|
||
} NDIS_TAPI_CLOSE, *PNDIS_TAPI_CLOSE;
|
||
|
||
fNotifyNDIS _ Indicates if NDIS needs to be notified about the completion
|
||
of this operation
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS: Line context destroyed succesfully.
|
||
|
||
NDIS_STATUS_PENDING: Close operation is pending. When line is closed,
|
||
tapi provider will be dereferenced.
|
||
|
||
NDIS_STATUS_TAPI_INVALLINEHANDLE: An invalid handle was supplied.
|
||
No operations performed.
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
LINE* pLine = NULL;
|
||
BOOLEAN fLockReleased = FALSE;
|
||
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpCloseLine") );
|
||
|
||
|
||
do
|
||
{
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpCloseLine: Invalid parameter") );
|
||
|
||
status = NDIS_STATUS_TAPI_INVALPARAM;
|
||
|
||
break;
|
||
}
|
||
|
||
pLine = TpGetLinePtrFromHdLineEx( pAdapter, pRequest->hdLine );
|
||
|
||
|
||
if ( pLine == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCloseLine: Invalid handle supplied") );
|
||
|
||
status = NDIS_STATUS_TAPI_INVALLINEHANDLE;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Remove line context from tapi providers line table
|
||
// and invalidate the handle, as we do not want any more
|
||
// requests on this line context.
|
||
//
|
||
// The active line counter will be adjusted in TpCloseLineComplete()
|
||
// when we deallocate the line context.
|
||
//
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
pAdapter->TapiProv.LineTable[ (ULONG) pRequest->hdLine ] = NULL;
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
//
|
||
// Now start closing the line
|
||
//
|
||
NdisAcquireSpinLock( &pLine->lockLine );
|
||
|
||
//
|
||
// Do not accept any more incoming calls
|
||
//
|
||
pLine->ulLnFlags &= ~LNBF_AcceptIncomingCalls;
|
||
|
||
//
|
||
// Mark the line as close pending, so that we do not accept
|
||
// any more requests on it
|
||
//
|
||
pLine->ulLnFlags |= LNBF_LineClosePending;
|
||
|
||
if ( fNotifyNDIS )
|
||
pLine->ulLnFlags |= LNBF_NotifyNDIS;
|
||
|
||
while ( !IsListEmpty( &pLine->linkCalls ) )
|
||
{
|
||
CALL* pCall = NULL;
|
||
NDIS_TAPI_CLOSE_CALL DummyRequest;
|
||
|
||
//
|
||
// Retrieve a call context from the head of active call list
|
||
// and close it.
|
||
//
|
||
pCall = (CALL*) CONTAINING_RECORD( pLine->linkCalls.Flink,
|
||
CALL,
|
||
linkCalls );
|
||
|
||
NdisReleaseSpinLock( &pLine->lockLine );
|
||
|
||
DummyRequest.hdCall = pCall->hdCall;
|
||
|
||
//
|
||
// This will remove the call from the list,
|
||
// so there will be a new call at the head of the list
|
||
// next time we retrieve.
|
||
//
|
||
TpCloseCall( pAdapter, &DummyRequest, FALSE );
|
||
|
||
NdisAcquireSpinLock( &pLine->lockLine );
|
||
}
|
||
|
||
status = NDIS_STATUS_PENDING;
|
||
|
||
} while ( FALSE );
|
||
|
||
if ( status == NDIS_STATUS_PENDING )
|
||
{
|
||
BOOLEAN fNotifyTapiOfInternalLineClose = !( pLine->ulLnFlags & LNBF_NotifyNDIS );
|
||
|
||
NdisReleaseSpinLock( &pLine->lockLine );
|
||
|
||
//
|
||
// Check if this is an internal request to close the line,
|
||
// notify TAPI if it is
|
||
//
|
||
if ( fNotifyTapiOfInternalLineClose )
|
||
{
|
||
NDIS_TAPI_EVENT TapiEvent;
|
||
|
||
NdisZeroMemory( &TapiEvent, sizeof( NDIS_TAPI_EVENT ) );
|
||
|
||
TapiEvent.htLine = pLine->htLine;
|
||
TapiEvent.ulMsg = LINE_CLOSE;
|
||
|
||
NdisMIndicateStatus( pLine->pAdapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_TAPI_INDICATION,
|
||
&TapiEvent,
|
||
sizeof( NDIS_TAPI_EVENT ) );
|
||
}
|
||
|
||
if ( pAdapter->TapiProv.nActiveLines == 1 )
|
||
{
|
||
//
|
||
// We are closing the last line so notify protocol about this so
|
||
// it can remove packet filters
|
||
//
|
||
WORKITEM* pWorkItem = NULL;
|
||
PVOID Args[4];
|
||
|
||
Args[0] = (PVOID) BN_ResetFiltersForCloseLine; // Is a reset filters request
|
||
Args[1] = (PVOID) pLine;
|
||
|
||
//
|
||
// Allocate work item for reenumerating bindings
|
||
//
|
||
pWorkItem = AllocWorkItem( &gl_llistWorkItems,
|
||
ExecBindingWorkItem,
|
||
NULL,
|
||
Args,
|
||
BWT_workPrStartBinds );
|
||
|
||
if ( pWorkItem )
|
||
{
|
||
//
|
||
// Schedule the work item.
|
||
//
|
||
// Note that we need to referencing here, because we do not want TpCloseLineCopmlete()
|
||
// to be called before the work item is executed.
|
||
//
|
||
// This reference will be removed when the work item is executed.
|
||
//
|
||
ReferenceLine( pLine, TRUE );
|
||
|
||
ScheduleWorkItem( pWorkItem );
|
||
|
||
//
|
||
// In this case this request will be completed later
|
||
//
|
||
status = NDIS_STATUS_PENDING;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Remove the reference added in line open
|
||
//
|
||
DereferenceLine( pLine );
|
||
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpCloseLine=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NDIS_STATUS
|
||
TpCloseCall(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_CLOSE_CALL pRequest,
|
||
IN BOOLEAN fNotifyNDIS
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function is called to close a call.
|
||
|
||
It will remove one of the references added in TpMakeCall() on the call
|
||
context.
|
||
|
||
It will be called from 2 places:
|
||
1. When miniport receives an OID_TAPI_CLOSE_CALL.
|
||
In this case, fNotifyNDIS will be set as TRUE.
|
||
|
||
2. When miniport is halting, TpCloseLine() will call
|
||
this function for every active call context.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_CLOSE_CALL
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_CALL hdCall;
|
||
|
||
} NDIS_TAPI_CLOSE_CALL, *PNDIS_TAPI_CLOSE_CALL;
|
||
|
||
|
||
fNotifyNDIS _ Indicates if NDIS needs to be notified about the completion
|
||
of this operation
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS: Call is succesfully closed and resources are freed.
|
||
|
||
NDIS_STATUS_PENDING: Call close is pending on active calls.
|
||
When call is closed the owning line context will be
|
||
dereferenced.
|
||
|
||
---------------------------------------------------------------------------*/
|
||
|
||
{
|
||
NDIS_STATUS status = NDIS_STATUS_FAILURE;
|
||
CALL* pCall = NULL;
|
||
BOOLEAN fLockReleased = FALSE;
|
||
BOOLEAN fDereferenceCall = FALSE;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpCloseCall") );
|
||
|
||
do
|
||
{
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpCloseCall: Invalid parameter") );
|
||
|
||
status = NDIS_STATUS_TAPI_INVALPARAM;
|
||
|
||
break;
|
||
}
|
||
|
||
pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(NDIS_HANDLE) pRequest->hdCall );
|
||
|
||
if ( pCall == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCloseCall: Invalid handle supplied") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Now start closing the call
|
||
//
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
/*
|
||
if ( !fNotifyNDIS )
|
||
{
|
||
//
|
||
// Request is not coming from TAPI directly, so see if we have informed TAPI of
|
||
// a new call, because if we have then we can not close the call now, we should
|
||
// wait for TAPI to close it.
|
||
//
|
||
if ( pCall->htCall )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCloseCall: Internal close request for a TAPI informed call, can not close now") );
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
status = NDIS_STATUS_FAILURE;
|
||
|
||
break;
|
||
}
|
||
|
||
}
|
||
*/
|
||
|
||
//
|
||
// See if call is already closed or closing
|
||
//
|
||
if ( pCall->ulClFlags & CLBF_CallClosePending ||
|
||
pCall->ulClFlags & CLBF_CallClosed )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCloseCall: Close request on an already closed call") );
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
status = NDIS_STATUS_FAILURE;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Mark call if we need to notify NDIS about the completion of close
|
||
//
|
||
if ( fNotifyNDIS )
|
||
pCall->ulClFlags |= CLBF_NotifyNDIS;
|
||
|
||
//
|
||
// Mark call as close pending
|
||
//
|
||
pCall->ulClFlags |= CLBF_CallClosePending;
|
||
|
||
//
|
||
// Drop the call first
|
||
//
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
//
|
||
// Drop will take care of unbinding and cancelling the timer
|
||
//
|
||
{
|
||
NDIS_TAPI_DROP DummyRequest;
|
||
|
||
DummyRequest.hdCall = pRequest->hdCall;
|
||
|
||
TpDropCall( pAdapter, &DummyRequest, 0 );
|
||
}
|
||
|
||
status = NDIS_STATUS_PENDING;
|
||
|
||
} while ( FALSE );
|
||
|
||
if ( status == NDIS_STATUS_SUCCESS ||
|
||
status == NDIS_STATUS_PENDING )
|
||
{
|
||
LINE* pLine = pCall->pLine;
|
||
|
||
//
|
||
// Remove call from line's active call list, and decrement
|
||
// active call counter
|
||
//
|
||
NdisAcquireSpinLock( &pLine->lockLine );
|
||
|
||
RemoveHeadList( pCall->linkCalls.Blink );
|
||
|
||
pLine->nActiveCalls--;
|
||
|
||
NdisReleaseSpinLock( &pLine->lockLine );
|
||
|
||
//
|
||
// We should now remove the call from the Tapi provider's call table,
|
||
// and invalidate its' handle
|
||
//
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
RemoveFromHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(NDIS_HANDLE) pCall->hdCall );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
//
|
||
// Remove the reference for close call
|
||
//
|
||
DereferenceCall( pCall );
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpCloseCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpDropCall(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_DROP pRequest,
|
||
IN ULONG ulLineDisconnectMode
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will be called from a couple of places:
|
||
1. If miniport receives an OID_TAPI_DROP_CALL request from TAPI.
|
||
|
||
2. When NIC for the call is unbound, it will call TpUnbindCall(),
|
||
and if the call is not dropped yet, it will call TpDropCall().
|
||
|
||
3. When the call is in connect pending stage but the call needs
|
||
to be dropped.
|
||
|
||
4. When session is up and call receives a PADT packet from the peer.
|
||
|
||
As this is a synchronous call, we do not need an fNotifyNDIS flag.
|
||
|
||
CAUTION: All locks must be released before calling this function.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adaptert information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_DROP
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_CALL hdCall;
|
||
IN ULONG ulUserUserInfoSize;
|
||
IN UCHAR UserUserInfo[1];
|
||
|
||
} NDIS_TAPI_DROP, *PNDIS_TAPI_DROP;
|
||
|
||
ulLineDisconnectMode _ Reason for dropping the call. This is reported
|
||
back to TAPI in the appropriate state change
|
||
notification.
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS: Call is succesfully dropped.
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
||
CALL* pCall = NULL;
|
||
BOOLEAN fSendPADT = FALSE;
|
||
BINDING* pBinding = NULL;
|
||
PPPOE_PACKET* pPacket = NULL;
|
||
BOOLEAN fTapiNotifiedOfNewCall = FALSE;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpDropCall") );
|
||
|
||
|
||
do
|
||
{
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpDropCall: Invalid parameter") );
|
||
|
||
|
||
status = NDIS_STATUS_TAPI_INVALPARAM;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Retrieve the pointer to call from the handle table
|
||
//
|
||
pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(NDIS_HANDLE) pRequest->hdCall );
|
||
|
||
if ( pCall == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpDropCall: Invalid handle supplied") );
|
||
|
||
break;
|
||
}
|
||
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
//
|
||
// Make sure call is not dropped or closed previously
|
||
//
|
||
if ( pCall->ulClFlags & CLBF_CallDropped || pCall->ulClFlags & CLBF_CallClosed)
|
||
{
|
||
//
|
||
// Call already dropped, quit
|
||
//
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
TRACE( TL_N, TM_Tp, ("TpDropCall: Call already dropped or closed") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Then we must be in open state either connected, or connect pending
|
||
//
|
||
ASSERT( pCall->ulClFlags & CLBF_CallOpen );
|
||
|
||
pCall->ulClFlags &= ~CLBF_CallOpen;
|
||
pCall->ulClFlags &= ~CLBF_CallConnectPending;
|
||
pCall->ulClFlags |= CLBF_CallDropped;
|
||
|
||
if ( pCall->htCall )
|
||
{
|
||
fTapiNotifiedOfNewCall = TRUE;
|
||
}
|
||
|
||
//
|
||
// Save the binding pointer as we will detach call from it soon
|
||
//
|
||
pBinding = pCall->pBinding;
|
||
|
||
if ( pCall->usSessionId && pBinding )
|
||
{
|
||
//
|
||
// Prepare a PADT packet to send if:
|
||
// - A session id is assigned to the call (which is different than fSessionUp)
|
||
// A session id is assigned to the call when the peer is informed about the session,
|
||
// however fSessionUp will be TRUE when NDISWAN is notified about the call
|
||
//
|
||
// - A binding exists to send the PADT packet
|
||
//
|
||
|
||
status = PacketInitializePADTToSend( &pPacket,
|
||
pCall->SrcAddr,
|
||
pCall->DestAddr,
|
||
pCall->usSessionId );
|
||
|
||
if ( status == NDIS_STATUS_SUCCESS )
|
||
{
|
||
//
|
||
// The following references are mandatory as in case PrSend() returns status pending,
|
||
// they will be removed by PrSendComplete()
|
||
//
|
||
ReferencePacket( pPacket );
|
||
|
||
ReferenceBinding( pBinding, TRUE );
|
||
|
||
fSendPADT = TRUE;
|
||
}
|
||
|
||
//
|
||
// Ignore the current status as this does not affect
|
||
// the status of the Drop operation.
|
||
//
|
||
status = NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Release the lock to take care of rest of the operation
|
||
//
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
//
|
||
// Cancels the timer if it is set, otherwise it will not have any effect.
|
||
//
|
||
TimerQCancelItem( &gl_TimerQ, &pCall->timerTimeout );
|
||
|
||
//
|
||
// Send PADT here if we need to
|
||
//
|
||
if ( fSendPADT )
|
||
{
|
||
NDIS_STATUS SendStatus;
|
||
|
||
SendStatus = PrSend( pBinding, pPacket );
|
||
|
||
PacketFree( pPacket );
|
||
}
|
||
|
||
//
|
||
// This will unbind us from the underlying NIC context if we are bound
|
||
//
|
||
if ( pBinding )
|
||
{
|
||
PrRemoveCallFromBinding( pBinding, pCall );
|
||
}
|
||
|
||
//
|
||
// If TAPI was already notified of the call, move it to disconnected state
|
||
//
|
||
if ( fTapiNotifiedOfNewCall )
|
||
{
|
||
TpCallStateChangeHandler( pCall,
|
||
LINECALLSTATE_DISCONNECTED,
|
||
ulLineDisconnectMode );
|
||
|
||
}
|
||
|
||
//
|
||
// Remove the reference added in TpMakeCall() that corresponds
|
||
// to the drop of the call.
|
||
//
|
||
DereferenceCall( pCall );
|
||
|
||
} while ( FALSE );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpDropCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
VOID
|
||
TpCloseCallComplete(
|
||
IN CALL* pCall
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will be called only from DereferenceCall().
|
||
It will only be called if ref count of the call drops to 0.
|
||
|
||
When this function is called, it will deallocate the call context,
|
||
and dereference the line context.
|
||
|
||
If call contexts CLBF_NotifyNDIS flag is set, then it will call
|
||
NdisMQueryInformationComplete().
|
||
|
||
Parameters:
|
||
|
||
pCall _ A pointer to the call context that will be freed.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
|
||
---------------------------------------------------------------------------*/
|
||
|
||
{
|
||
LINE* pLine = NULL;
|
||
|
||
ASSERT( VALIDATE_CALL( pCall ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpCloseCallComplete") );
|
||
|
||
//
|
||
// No need to use spin locks here, as our ref count has dropped to 0, and
|
||
// we should not be getting anymore requests on this call
|
||
//
|
||
pLine = pCall->pLine;
|
||
|
||
//
|
||
// CAUTION: Give an NDIS_MAC_LINE_DOWN indication here.
|
||
// It would be better to give this at drop time, but in that case
|
||
// there is a small timing window where NdisLinkHandle will be invalid
|
||
// and although NDISWAN protects itself against invalid handles, it might
|
||
// assert in checked builds, so instead I will do it here.
|
||
//
|
||
// If problems occur with this approach, then I will do it at drop time.
|
||
//
|
||
if ( pCall->stateCall == CL_stateSessionUp )
|
||
{
|
||
NDIS_MAC_LINE_DOWN LineDownInfo;
|
||
|
||
//
|
||
// Fill-in the line down structure
|
||
//
|
||
LineDownInfo.NdisLinkContext = pCall->NdisLinkContext;
|
||
|
||
//
|
||
// Reflect the change onto the call
|
||
//
|
||
pCall->stateCall = CL_stateDisconnected;
|
||
|
||
pCall->NdisLinkContext = 0;
|
||
|
||
TRACE( TL_N, TM_Tp, ("TpCloseCallComplete: Indicate NDIS_STATUS_WAN_LINE_DOWN") );
|
||
|
||
NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_WAN_LINE_DOWN,
|
||
&LineDownInfo,
|
||
sizeof( NDIS_MAC_LINE_DOWN ) );
|
||
|
||
}
|
||
|
||
if ( pCall->ulClFlags & CLBF_NotifyNDIS )
|
||
{
|
||
|
||
TRACE( TL_N, TM_Tp, ("TpCloseCallComplete: Notifying NDIS") );
|
||
|
||
//
|
||
// The close call was a result of OID_TAPI_CLOSE_CALL request so complete the request.
|
||
// There is a small timing window where this call may happen before MpSetInformation()
|
||
// returns NDIS_STATUS_PENDING, but ArvindM says this is not a problem.
|
||
//
|
||
NdisMSetInformationComplete( pLine->pAdapter->MiniportAdapterHandle, NDIS_STATUS_SUCCESS );
|
||
}
|
||
|
||
//
|
||
// Clean up the call context
|
||
//
|
||
TpCallCleanup( pCall );
|
||
|
||
//
|
||
// Remove the reference on the owning line
|
||
//
|
||
DereferenceLine( pLine );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpCloseCallComplete") );
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
TpCloseLineComplete(
|
||
IN LINE* pLine
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will be called to indicate that a line has been closed, and
|
||
the line context can be freed.
|
||
|
||
It will only be called from DereferenceLine() if ref count on the line context
|
||
drops to 0.
|
||
|
||
It will also remove the reference on the owning tapi provider context.
|
||
|
||
Parameters:
|
||
|
||
pLine _ A pointer to our line information structure that is closed
|
||
and ready to be deallocated.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
IN ADAPTER* pAdapter = NULL;
|
||
|
||
ASSERT( VALIDATE_LINE( pLine ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpCloseLineComplete") );
|
||
|
||
pAdapter = pLine->pAdapter;
|
||
|
||
//
|
||
// Decrement the tapi provider's active line counter
|
||
//
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
pAdapter->TapiProv.nActiveLines--;
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
//
|
||
// Notify NDIS if necesarry
|
||
//
|
||
if ( pLine->ulLnFlags & LNBF_NotifyNDIS )
|
||
{
|
||
|
||
TRACE( TL_N, TM_Tp, ("TpCloseLineComplete: Notifying NDIS") );
|
||
|
||
//
|
||
// Line was closed as a result of OID_TAPI_CLOSE request,
|
||
// so indicate the completion.
|
||
//
|
||
NdisMSetInformationComplete( pAdapter->MiniportAdapterHandle, NDIS_STATUS_SUCCESS );
|
||
}
|
||
|
||
//
|
||
// Clean up line context
|
||
//
|
||
TpLineCleanup( pLine );
|
||
|
||
//
|
||
// Remove the reference on the owning tapi provider
|
||
//
|
||
DereferenceTapiProv( pAdapter );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpCloseLineComplete") );
|
||
}
|
||
|
||
VOID
|
||
TpProviderShutdownComplete(
|
||
IN ADAPTER* pAdapter
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will only be called from DereferenceTapiProv() if ref count
|
||
on the tapi provider object drops to 0.
|
||
|
||
It will do the necesarry clean up on the tapi provider context, and dereference
|
||
the owning adapter context.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpProviderShutdownComplete") );
|
||
|
||
//
|
||
// See if we need to notify NDIS about the completion of shut down.
|
||
//
|
||
if ( pAdapter->TapiProv.ulTpFlags & TPBF_NotifyNDIS )
|
||
{
|
||
|
||
TRACE( TL_N, TM_Tp, ("TpProviderShutdownComplete: Notifying NDIS") );
|
||
|
||
//
|
||
// Tapi was shut down as a result of OID_TAPI_PROVIDER_SHUTDOWN request,
|
||
// so indicate the completion.
|
||
//
|
||
NdisMSetInformationComplete( pAdapter->MiniportAdapterHandle, NDIS_STATUS_SUCCESS );
|
||
}
|
||
|
||
//
|
||
// Clean up tapi provider
|
||
//
|
||
TpProviderCleanup( pAdapter );
|
||
|
||
//
|
||
// Remove the reference on the owning adapter context
|
||
//
|
||
DereferenceAdapter( pAdapter );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpProviderShutdownComplete") );
|
||
|
||
}
|
||
|
||
VOID
|
||
TpProviderCleanup(
|
||
IN ADAPTER* pAdapter
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will do the necesarry clean up on the tapi provider deallocating
|
||
all of its resources.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpProviderCleanup") );
|
||
|
||
if ( pAdapter )
|
||
{
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
if ( pAdapter->TapiProv.LineTable )
|
||
{
|
||
NdisFreeMemory( pAdapter->TapiProv.LineTable,
|
||
sizeof( LINE* ) * pAdapter->nMaxLines,
|
||
0 );
|
||
|
||
pAdapter->TapiProv.LineTable = NULL;
|
||
}
|
||
|
||
if ( pAdapter->TapiProv.hCallTable )
|
||
{
|
||
FreeHandleTable( pAdapter->TapiProv.hCallTable );
|
||
|
||
pAdapter->TapiProv.hCallTable = NULL;
|
||
}
|
||
|
||
NdisZeroMemory( &pAdapter->TapiProv, sizeof( pAdapter->TapiProv ) );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpProviderCleanup") );
|
||
}
|
||
|
||
VOID
|
||
TpLineCleanup(
|
||
IN LINE* pLine
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will do the necesarry clean up on the line context deallocating
|
||
all of its resources.
|
||
|
||
Parameters:
|
||
|
||
pLine _ A pointer to our line information structure.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
ASSERT( VALIDATE_LINE( pLine ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpLineCleanup") );
|
||
|
||
NdisFreeSpinLock( &pLine->lockLine );
|
||
|
||
FREE_LINE( pLine );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpLineCleanup") );
|
||
}
|
||
|
||
VOID
|
||
TpCallCleanup(
|
||
IN CALL* pCall
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will do the necesarry clean up on the call context deallocating
|
||
all of its resources.
|
||
|
||
Parameters:
|
||
|
||
pCall _ A pointer to our call information structure.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
PPPOE_PACKET* pPacket = NULL;
|
||
LIST_ENTRY* pLink = NULL;
|
||
|
||
ASSERT( VALIDATE_CALL( pCall ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpCallCleanup") );
|
||
|
||
NdisFreeSpinLock( &pCall->lockCall );
|
||
|
||
if ( pCall->pSendPacket )
|
||
PacketFree( pCall->pSendPacket );
|
||
|
||
while ( pCall->nReceivedPackets > 0 )
|
||
{
|
||
pLink = RemoveHeadList( &pCall->linkReceivedPackets );
|
||
|
||
pCall->nReceivedPackets--;
|
||
|
||
pPacket = (PPPOE_PACKET*) CONTAINING_RECORD( pLink, PPPOE_PACKET, linkPackets );
|
||
|
||
DereferencePacket( pPacket );
|
||
}
|
||
|
||
FREE_CALL( pCall );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpCallCleanup") );
|
||
}
|
||
|
||
|
||
NDIS_STATUS
|
||
TpSetDefaultMediaDetection(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request informs the miniport of the new set of media modes to detect
|
||
for the indicated line (replacing any previous set).
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_LINE hdLine;
|
||
IN ULONG ulMediaModes;
|
||
|
||
} NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION, *
|
||
PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_TAPI_INVALLINEHANDLE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
LINE* pLine = NULL;
|
||
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpSetDefaultMediaDetection") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpSetDefaultMediaDetection: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetection=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
//
|
||
// Retrieve the pointer to line context
|
||
//
|
||
pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
|
||
|
||
if ( pLine == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetection=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALLINEHANDLE;
|
||
}
|
||
|
||
//
|
||
// We only accept this request if we are not in client mode, and digital media
|
||
// is one of the modes proposed
|
||
//
|
||
if ( ( pRequest->ulMediaModes & LINEMEDIAMODE_DIGITALDATA ) && !pAdapter->fClientRole )
|
||
{
|
||
pLine->ulLnFlags |= LNBF_AcceptIncomingCalls;
|
||
}
|
||
else
|
||
{
|
||
pLine->ulLnFlags &= ~LNBF_AcceptIncomingCalls;
|
||
}
|
||
|
||
{
|
||
//
|
||
// Schedule a work item to reenumerate bindings
|
||
//
|
||
WORKITEM* pWorkItem = NULL;
|
||
PVOID Args[4];
|
||
|
||
Args[0] = (PVOID) BN_SetFiltersForMediaDetection; // Is a set filters request
|
||
Args[1] = (PVOID) pLine;
|
||
Args[2] = (PVOID) pRequest;
|
||
|
||
//
|
||
// Allocate work item for reenumerating bindings
|
||
//
|
||
pWorkItem = AllocWorkItem( &gl_llistWorkItems,
|
||
ExecBindingWorkItem,
|
||
NULL,
|
||
Args,
|
||
BWT_workPrStartBinds );
|
||
|
||
if ( pWorkItem )
|
||
{
|
||
//
|
||
// Schedule work item.
|
||
//
|
||
// Note that we do not need to referencing becaue we are not completing
|
||
// the query information request at this point, so nothing can go wrong
|
||
// untill it is completed, and it will be done when the work item is executed.
|
||
//
|
||
ScheduleWorkItem( pWorkItem );
|
||
|
||
//
|
||
// In this case this request will be completed later
|
||
//
|
||
status = NDIS_STATUS_PENDING;
|
||
}
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetection=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
VOID
|
||
TpSetDefaultMediaDetectionComplete(
|
||
IN LINE* pLine,
|
||
IN PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pRequest
|
||
)
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("+TpSetDefaultMediaDetectionComplete") );
|
||
|
||
NdisMQueryInformationComplete( pLine->pAdapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_SUCCESS );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetectionComplete=$%x", NDIS_STATUS_SUCCESS) );
|
||
}
|
||
|
||
|
||
#define TAPI_EXT_VERSION 0x00010000
|
||
|
||
NDIS_STATUS
|
||
TpNegotiateExtVersion(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_NEGOTIATE_EXT_VERSION pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request returns the highest extension version number the service
|
||
provider is willing to operate under for this device given the range of
|
||
possible extension versions.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_NEGOTIATE_EXT_VERSION
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN ULONG ulDeviceID;
|
||
IN ULONG ulLowVersion;
|
||
IN ULONG ulHighVersion;
|
||
OUT ULONG ulExtVersion;
|
||
} NDIS_TAPI_NEGOTIATE_EXT_VERSION, *PNDIS_TAPI_NEGOTIATE_EXT_VERSION;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpNegotiateExtVersion") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpNegotiateExtVersion: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpNegotiateExtVersion=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
//
|
||
// Make sure the miniport's version number is within the allowable
|
||
// range requested by the caller.
|
||
//
|
||
// We ignore the ulDeviceID because the version information applies
|
||
// to all devices on this adapter.
|
||
//
|
||
if ( TAPI_EXT_VERSION < pRequest->ulLowVersion ||
|
||
TAPI_EXT_VERSION > pRequest->ulHighVersion )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpNegotiateExtVersion=$%x",NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION) );
|
||
|
||
return NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION;
|
||
}
|
||
|
||
//
|
||
// Looks like we're compatible, so tell the caller what we expect.
|
||
//
|
||
pRequest->ulExtVersion = TAPI_EXT_VERSION;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpNegotiateExtVersion=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpGetExtensionId(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_GET_EXTENSION_ID pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request returns the extension ID that the miniport supports for the
|
||
indicated line device.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_GET_EXTENSION_ID
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN ULONG ulDeviceID;
|
||
OUT LINE_EXTENSION_ID LineExtensionID;
|
||
|
||
} NDIS_TAPI_GET_EXTENSION_ID, *PNDIS_TAPI_GET_EXTENSION_ID;
|
||
|
||
typedef struct _LINE_EXTENSION_ID
|
||
{
|
||
ULONG ulExtensionID0;
|
||
ULONG ulExtensionID1;
|
||
ULONG ulExtensionID2;
|
||
ULONG ulExtensionID3;
|
||
|
||
} LINE_EXTENSION_ID, *PLINE_EXTENSION_ID;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_TAPI_NODRIVER
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
HDRV_LINE hdLine = INVALID_LINE_HANDLE;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpGetExtensionId") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpGetExtensionId: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetExtensionId=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
//
|
||
// Retrieve the handle to line context
|
||
//
|
||
hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
|
||
|
||
if ( hdLine == INVALID_LINE_HANDLE )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetExtensionId=$%x",NDIS_STATUS_TAPI_NODRIVER) );
|
||
|
||
return NDIS_STATUS_TAPI_NODRIVER;
|
||
}
|
||
|
||
//
|
||
// This driver does not support any extensions, so we return zeros.
|
||
//
|
||
pRequest->LineExtensionID.ulExtensionID0 = 0;
|
||
pRequest->LineExtensionID.ulExtensionID1 = 0;
|
||
pRequest->LineExtensionID.ulExtensionID2 = 0;
|
||
pRequest->LineExtensionID.ulExtensionID3 = 0;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetExtensionId=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpGetAddressStatus(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_GET_ADDRESS_STATUS pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request queries the specified address for its current status.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_GET_ADDRESS_STATUS
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_LINE hdLine;
|
||
IN ULONG ulAddressID;
|
||
OUT LINE_ADDRESS_STATUS LineAddressStatus;
|
||
|
||
} NDIS_TAPI_GET_ADDRESS_STATUS, *PNDIS_TAPI_GET_ADDRESS_STATUS;
|
||
|
||
typedef struct _LINE_ADDRESS_STATUS
|
||
{
|
||
ULONG ulTotalSize;
|
||
ULONG ulNeededSize;
|
||
ULONG ulUsedSize;
|
||
|
||
ULONG ulNumInUse;
|
||
ULONG ulNumActiveCalls;
|
||
ULONG ulNumOnHoldCalls;
|
||
ULONG ulNumOnHoldPendCalls;
|
||
ULONG ulAddressFeatures;
|
||
|
||
ULONG ulNumRingsNoAnswer;
|
||
ULONG ulForwardNumEntries;
|
||
ULONG ulForwardSize;
|
||
ULONG ulForwardOffset;
|
||
|
||
ULONG ulTerminalModesSize;
|
||
ULONG ulTerminalModesOffset;
|
||
|
||
ULONG ulDevSpecificSize;
|
||
ULONG ulDevSpecificOffset;
|
||
|
||
} LINE_ADDRESS_STATUS, *PLINE_ADDRESS_STATUS;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_FAILURE
|
||
NDIS_STATUS_TAPI_INVALLINEHANDLE
|
||
NDIS_STATUS_TAPI_INVALADDRESSID
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
LINE* pLine = NULL;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpGetAddressStatus") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpGetAddressStatus: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
//
|
||
// Retrieve the pointer to line context
|
||
//
|
||
pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
|
||
|
||
if ( pLine == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALLINEHANDLE;
|
||
}
|
||
|
||
pRequest->LineAddressStatus.ulNeededSize = sizeof( LINE_ADDRESS_STATUS );
|
||
|
||
if ( pRequest->LineAddressStatus.ulTotalSize < pRequest->LineAddressStatus.ulNeededSize )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_INVALID_LENGTH) );
|
||
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
pRequest->LineAddressStatus.ulUsedSize = pRequest->LineAddressStatus.ulNeededSize;
|
||
|
||
//
|
||
// Make sure the address is within range - we only support one per line.
|
||
//
|
||
if ( pRequest->ulAddressID > 1 )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_TAPI_INVALADDRESSID) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALADDRESSID;
|
||
}
|
||
|
||
//
|
||
// Return the current status information for the address
|
||
//
|
||
pRequest->LineAddressStatus.ulNumInUse = ( pLine->nActiveCalls > 0 ) ? 1 : 0;
|
||
|
||
pRequest->LineAddressStatus.ulNumActiveCalls = pLine->nActiveCalls;
|
||
|
||
pRequest->LineAddressStatus.ulAddressFeatures = ( pLine->nActiveCalls < pLine->nMaxCalls ) ?
|
||
LINEADDRFEATURE_MAKECALL :
|
||
0;
|
||
|
||
pRequest->LineAddressStatus.ulNumRingsNoAnswer = 999;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
#define TAPI_DEVICECLASS_NAME "tapi/line"
|
||
#define TAPI_DEVICECLASS_ID 1
|
||
#define NDIS_DEVICECLASS_NAME "ndis"
|
||
#define NDIS_DEVICECLASS_ID 2
|
||
|
||
NDIS_STATUS
|
||
TpGetId(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_GET_ID pRequest,
|
||
IN ULONG ulRequestLength
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request returns a device ID for the specified device class
|
||
associated with the selected line, address or call.
|
||
|
||
Currently, there are two types of this request that must be supported by WAN
|
||
NIC drivers:
|
||
|
||
1. IN DeviceClass = "ndis" // case insensitive
|
||
IN ulSelect = LINECALLSELECT_CALL
|
||
IN hdCall = ActiveCallHandle
|
||
OUT DeviceID = ConnectionWrapperID
|
||
|
||
DeviceID should be set to the NdisLinkContext handle returned by NDISWAN in
|
||
the NDIS_MAC_LINE_UP structure for the initial NDIS_STATUS_WAN_LINE_UP
|
||
indication to establish the link.
|
||
|
||
The miniport must make the initial line-up indication to establish a link (or
|
||
open a data channel on a line) before returning from this request in order to
|
||
supply this DeviceID value.
|
||
|
||
2. IN DeviceClass = "tapi/line" // case insensitive
|
||
IN ulSelect = LINECALLSELECT_LINE
|
||
IN hdLine = OpenLineHandle
|
||
OUT DeviceID = ulDeviceID
|
||
|
||
DeviceID will be set to the miniport-determined DeviceID associated with the
|
||
line handle.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_GET_ID
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_LINE hdLine;
|
||
IN ULONG ulAddressID;
|
||
IN HDRV_CALL hdCall;
|
||
IN ULONG ulSelect;
|
||
IN ULONG ulDeviceClassSize;
|
||
IN ULONG ulDeviceClassOffset;
|
||
OUT VAR_STRING DeviceID;
|
||
|
||
} NDIS_TAPI_GET_ID, *PNDIS_TAPI_GET_ID;
|
||
|
||
typedef struct _VAR_STRING
|
||
{
|
||
ULONG ulTotalSize;
|
||
ULONG ulNeededSize;
|
||
ULONG ulUsedSize;
|
||
|
||
ULONG ulStringFormat;
|
||
ULONG ulStringSize;
|
||
ULONG ulStringOffset;
|
||
|
||
} VAR_STRING, *PVAR_STRING;
|
||
|
||
ulRequestLength _ Length of the request buffer
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_FAILURE
|
||
NDIS_STATUS_TAPI_INVALDEVICECLASS
|
||
NDIS_STATUS_TAPI_INVALLINEHANDLE
|
||
NDIS_STATUS_TAPI_INVALADDRESSID
|
||
NDIS_STATUS_TAPI_INVALCALLHANDLE
|
||
NDIS_STATUS_TAPI_OPERATIONUNAVAIL
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
||
BOOLEAN fNotifyNDIS = FALSE;
|
||
|
||
LINE* pLine = NULL;
|
||
CALL* pCall = NULL;
|
||
|
||
UINT DeviceClass;
|
||
|
||
PUCHAR IDPtr;
|
||
UINT IDLength;
|
||
ULONG_PTR DeviceID;
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpGetId") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpGetId: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
if ( pRequest->ulDeviceClassOffset + pRequest->ulDeviceClassSize > ulRequestLength )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
if ( pRequest->ulSelect == LINECALLSELECT_LINE )
|
||
{
|
||
|
||
if ( ( pRequest->ulDeviceClassSize == sizeof(TAPI_DEVICECLASS_NAME) ) &&
|
||
( _strnicmp(
|
||
(PCHAR) pRequest + pRequest->ulDeviceClassOffset,
|
||
TAPI_DEVICECLASS_NAME,
|
||
pRequest->ulDeviceClassSize
|
||
) == 0 ) )
|
||
{
|
||
DeviceClass = TAPI_DEVICECLASS_ID;
|
||
|
||
//
|
||
// Do the size check up front
|
||
//
|
||
IDLength = sizeof(DeviceID);
|
||
|
||
pRequest->DeviceID.ulNeededSize = sizeof(VAR_STRING) + IDLength;
|
||
|
||
if ( pRequest->DeviceID.ulTotalSize < pRequest->DeviceID.ulNeededSize )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_INVALID_LENGTH) );
|
||
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
pRequest->DeviceID.ulUsedSize = pRequest->DeviceID.ulNeededSize;
|
||
|
||
}
|
||
else // UNSUPPORTED DEVICE CLASS
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALDEVICECLASS) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALDEVICECLASS;
|
||
}
|
||
|
||
}
|
||
else if ( pRequest->ulSelect == LINECALLSELECT_CALL )
|
||
{
|
||
|
||
if ( ( pRequest->ulDeviceClassSize == sizeof(NDIS_DEVICECLASS_NAME) ) &&
|
||
( _strnicmp(
|
||
(PCHAR) pRequest + pRequest->ulDeviceClassOffset,
|
||
NDIS_DEVICECLASS_NAME,
|
||
pRequest->ulDeviceClassSize
|
||
) == 0 ) )
|
||
{
|
||
DeviceClass = NDIS_DEVICECLASS_ID;
|
||
|
||
//
|
||
// Do the size check up front
|
||
//
|
||
IDLength = sizeof(DeviceID);
|
||
|
||
pRequest->DeviceID.ulNeededSize = sizeof(VAR_STRING) + IDLength;
|
||
|
||
if ( pRequest->DeviceID.ulTotalSize < pRequest->DeviceID.ulNeededSize )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_INVALID_LENGTH) );
|
||
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
pRequest->DeviceID.ulUsedSize = pRequest->DeviceID.ulNeededSize;
|
||
|
||
}
|
||
else // UNSUPPORTED DEVICE CLASS
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALDEVICECLASS) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALDEVICECLASS;
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Find the link structure associated with the request/deviceclass.
|
||
//
|
||
if ( pRequest->ulSelect == LINECALLSELECT_LINE )
|
||
{
|
||
ASSERT( DeviceClass == TAPI_DEVICECLASS_ID );
|
||
ASSERT( IDLength == sizeof( DeviceID ) );
|
||
//
|
||
// Retrieve the pointer to line context
|
||
//
|
||
pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
|
||
|
||
if ( pLine == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALLINEHANDLE;
|
||
}
|
||
|
||
//
|
||
// TAPI just wants the ulDeviceID for this line.
|
||
//
|
||
DeviceID = (ULONG) pLine->hdLine + pAdapter->TapiProv.ulDeviceIDBase ;
|
||
IDPtr = (PUCHAR) &DeviceID;
|
||
|
||
}
|
||
else if ( pRequest->ulSelect == LINECALLSELECT_ADDRESS )
|
||
{
|
||
|
||
//
|
||
// Retrieve the pointer to line context
|
||
//
|
||
pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
|
||
|
||
if ( pLine == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALLINEHANDLE;
|
||
}
|
||
|
||
|
||
if ( pRequest->ulAddressID > 1 )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALADDRESSID) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALADDRESSID;
|
||
}
|
||
|
||
//
|
||
// Currently, there is no defined return value for this case...
|
||
// This is just a place holder for future extensions.
|
||
//
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALDEVICECLASS) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALDEVICECLASS;
|
||
|
||
}
|
||
else if ( pRequest->ulSelect == LINECALLSELECT_CALL )
|
||
{
|
||
BOOLEAN fCallReferenced = FALSE;
|
||
|
||
ASSERT( DeviceClass == NDIS_DEVICECLASS_ID );
|
||
ASSERT( IDLength == sizeof( DeviceID ) );
|
||
|
||
//
|
||
// Retrieve the pointer to call context
|
||
//
|
||
pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(NDIS_HANDLE) pRequest->hdCall );
|
||
|
||
if ( pCall == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALLINEHANDLE;
|
||
}
|
||
|
||
//
|
||
// We can only return this if we have a valid NdisLinkContext,
|
||
// and if our session is up, then our link handle must be valid
|
||
//
|
||
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
if ( pCall->ulTapiCallState == LINECALLSTATE_CONNECTED )
|
||
{
|
||
//
|
||
// Give a line-up indication to NDISWAN and obtain its handle
|
||
//
|
||
NDIS_MAC_LINE_UP LineUpInfo;
|
||
|
||
//
|
||
// Fill-in the line up structure
|
||
//
|
||
NdisZeroMemory( &LineUpInfo, sizeof( LineUpInfo ) );
|
||
|
||
LineUpInfo.LinkSpeed = pCall->ulSpeed;
|
||
LineUpInfo.Quality = NdisWanErrorControl;
|
||
LineUpInfo.SendWindow = 0;
|
||
|
||
LineUpInfo.ConnectionWrapperID = (NDIS_HANDLE) pCall->htCall;
|
||
LineUpInfo.NdisLinkHandle = (NDIS_HANDLE) pCall->hdCall;
|
||
LineUpInfo.NdisLinkContext = 0;
|
||
|
||
//
|
||
// Reference the call once and deref it just after indication of status
|
||
// to NDISWAN
|
||
//
|
||
ReferenceCall( pCall, FALSE );
|
||
|
||
fCallReferenced = TRUE;
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
TRACE( TL_N, TM_Tp, ("TpGetId: Indicate NDIS_STATUS_WAN_LINE_UP") );
|
||
|
||
NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_WAN_LINE_UP,
|
||
&LineUpInfo,
|
||
sizeof( NDIS_MAC_LINE_UP ) );
|
||
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
//
|
||
// Set state to indicate that session is established
|
||
//
|
||
pCall->stateCall = CL_stateSessionUp;
|
||
|
||
//
|
||
// Set link context obtained from NDISWAN on the call context
|
||
//
|
||
pCall->NdisLinkContext = LineUpInfo.NdisLinkContext;
|
||
|
||
DeviceID = (ULONG_PTR) pCall->NdisLinkContext;
|
||
IDPtr = (PUCHAR) &DeviceID;
|
||
|
||
//
|
||
// Since the session is up, schedule the MpIndicateReceivedPackets() handler
|
||
//
|
||
MpScheduleIndicateReceivedPacketsHandler( pCall );
|
||
|
||
status = NDIS_STATUS_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
status = NDIS_STATUS_TAPI_OPERATIONUNAVAIL;
|
||
}
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
if ( fCallReferenced )
|
||
{
|
||
DereferenceCall( pCall );
|
||
}
|
||
|
||
}
|
||
else // UNSUPPORTED SELECT REQUEST
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_FAILURE) );
|
||
|
||
return NDIS_STATUS_FAILURE;
|
||
}
|
||
|
||
if ( status == NDIS_STATUS_SUCCESS )
|
||
{
|
||
//
|
||
// Now we need to place the device ID.
|
||
//
|
||
pRequest->DeviceID.ulStringFormat = STRINGFORMAT_BINARY;
|
||
pRequest->DeviceID.ulStringSize = IDLength;
|
||
pRequest->DeviceID.ulStringOffset = sizeof(VAR_STRING);
|
||
|
||
NdisMoveMemory(
|
||
(PCHAR) &pRequest->DeviceID + sizeof(VAR_STRING),
|
||
IDPtr,
|
||
IDLength
|
||
);
|
||
}
|
||
|
||
if ( fNotifyNDIS )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpGetId:Completing delayed request") );
|
||
|
||
NdisMQueryInformationComplete( pCall->pLine->pAdapter->MiniportAdapterHandle, status );
|
||
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",status) );
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
#define TAPI_PROVIDER_STRING "VPN\0RASPPPOE"
|
||
#define TAPI_LINE_NAME "RAS PPPoE Line"
|
||
#define TAPI_LINE_NUM "0000"
|
||
|
||
NDIS_STATUS
|
||
TpGetDevCaps(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_GET_DEV_CAPS pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request queries a specified line device to determine its telephony
|
||
capabilities. The returned information is valid for all addresses on the
|
||
line device.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_GET_DEV_CAPS
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN ULONG ulDeviceID;
|
||
IN ULONG ulExtVersion;
|
||
OUT LINE_DEV_CAPS LineDevCaps;
|
||
|
||
} NDIS_TAPI_GET_DEV_CAPS, *PNDIS_TAPI_GET_DEV_CAPS;
|
||
|
||
typedef struct _LINE_DEV_CAPS
|
||
{
|
||
ULONG ulTotalSize;
|
||
ULONG ulNeededSize;
|
||
ULONG ulUsedSize;
|
||
|
||
ULONG ulProviderInfoSize;
|
||
ULONG ulProviderInfoOffset;
|
||
|
||
ULONG ulSwitchInfoSize;
|
||
ULONG ulSwitchInfoOffset;
|
||
|
||
ULONG ulPermanentLineID;
|
||
ULONG ulLineNameSize;
|
||
ULONG ulLineNameOffset;
|
||
ULONG ulStringFormat;
|
||
|
||
ULONG ulAddressModes;
|
||
ULONG ulNumAddresses;
|
||
ULONG ulBearerModes;
|
||
ULONG ulMaxRate;
|
||
ULONG ulMediaModes;
|
||
|
||
ULONG ulGenerateToneModes;
|
||
ULONG ulGenerateToneMaxNumFreq;
|
||
ULONG ulGenerateDigitModes;
|
||
ULONG ulMonitorToneMaxNumFreq;
|
||
ULONG ulMonitorToneMaxNumEntries;
|
||
ULONG ulMonitorDigitModes;
|
||
ULONG ulGatherDigitsMinTimeout;
|
||
ULONG ulGatherDigitsMaxTimeout;
|
||
|
||
ULONG ulMedCtlDigitMaxListSize;
|
||
ULONG ulMedCtlMediaMaxListSize;
|
||
ULONG ulMedCtlToneMaxListSize;
|
||
ULONG ulMedCtlCallStateMaxListSize;
|
||
|
||
ULONG ulDevCapFlags;
|
||
ULONG ulMaxNumActiveCalls;
|
||
ULONG ulAnswerMode;
|
||
ULONG ulRingModes;
|
||
ULONG ulLineStates;
|
||
|
||
ULONG ulUUIAcceptSize;
|
||
ULONG ulUUIAnswerSize;
|
||
ULONG ulUUIMakeCallSize;
|
||
ULONG ulUUIDropSize;
|
||
ULONG ulUUISendUserUserInfoSize;
|
||
ULONG ulUUICallInfoSize;
|
||
|
||
LINE_DIAL_PARAMS MinDialParams;
|
||
LINE_DIAL_PARAMS MaxDialParams;
|
||
LINE_DIAL_PARAMS DefaultDialParams;
|
||
|
||
ULONG ulNumTerminals;
|
||
ULONG ulTerminalCapsSize;
|
||
ULONG ulTerminalCapsOffset;
|
||
ULONG ulTerminalTextEntrySize;
|
||
ULONG ulTerminalTextSize;
|
||
ULONG ulTerminalTextOffset;
|
||
|
||
ULONG ulDevSpecificSize;
|
||
ULONG ulDevSpecificOffset;
|
||
|
||
} LINE_DEV_CAPS, *PLINE_DEV_CAPS;
|
||
|
||
typedef struct _LINE_DIAL_PARAMS
|
||
{
|
||
ULONG ulDialPause;
|
||
ULONG ulDialSpeed;
|
||
ULONG ulDigitDuration;
|
||
ULONG ulWaitForDialtone;
|
||
|
||
} LINE_DIAL_PARAMS, *PLINE_DIAL_PARAMS;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_TAPI_NODRIVER
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
HDRV_LINE hdLine = INVALID_LINE_HANDLE;
|
||
CHAR szTapiLineNum[] = TAPI_LINE_NUM;
|
||
CHAR *pBuf = NULL;
|
||
ULONG ulDeviceId;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpGetDevCaps") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpGetDevCaps: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
//
|
||
// Retrieve the handle to line context
|
||
//
|
||
hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
|
||
|
||
if ( hdLine == INVALID_LINE_HANDLE )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_TAPI_NODRIVER) );
|
||
|
||
return NDIS_STATUS_TAPI_NODRIVER;
|
||
}
|
||
|
||
pRequest->LineDevCaps.ulNeededSize = sizeof( LINE_DEV_CAPS ) +
|
||
sizeof( TAPI_PROVIDER_STRING ) +
|
||
( sizeof( TAPI_LINE_NAME ) - 1 ) +
|
||
sizeof( TAPI_LINE_NUM );
|
||
|
||
if ( pRequest->LineDevCaps.ulTotalSize < pRequest->LineDevCaps.ulNeededSize )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_INVALID_LENGTH) );
|
||
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
pRequest->LineDevCaps.ulUsedSize = pRequest->LineDevCaps.ulNeededSize;
|
||
|
||
pRequest->LineDevCaps.ulAddressModes = LINEADDRESSMODE_ADDRESSID |
|
||
LINEADDRESSMODE_DIALABLEADDR;
|
||
|
||
pRequest->LineDevCaps.ulNumAddresses = 1;
|
||
|
||
pRequest->LineDevCaps.ulBearerModes = LINEBEARERMODE_DATA;
|
||
|
||
pRequest->LineDevCaps.ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
|
||
|
||
pRequest->LineDevCaps.ulMaxNumActiveCalls = pAdapter->nCallsPerLine;
|
||
|
||
pRequest->LineDevCaps.ulAnswerMode = LINEANSWERMODE_DROP;
|
||
|
||
pRequest->LineDevCaps.ulRingModes = 1;
|
||
|
||
pRequest->LineDevCaps.ulPermanentLineID = pRequest->ulDeviceID;
|
||
|
||
pRequest->LineDevCaps.ulMaxRate = 0;
|
||
|
||
pRequest->LineDevCaps.ulMediaModes = LINEMEDIAMODE_DIGITALDATA;
|
||
|
||
//
|
||
// Insert the provider string and enumerated line name into line dev caps
|
||
//
|
||
pRequest->LineDevCaps.ulStringFormat = STRINGFORMAT_ASCII;
|
||
|
||
{
|
||
INT i;
|
||
|
||
//
|
||
// Tack on the ProviderString to the end of the LineDevCaps structure
|
||
//
|
||
pRequest->LineDevCaps.ulProviderInfoSize = sizeof( TAPI_PROVIDER_STRING );
|
||
|
||
pRequest->LineDevCaps.ulProviderInfoOffset = sizeof( pRequest->LineDevCaps );
|
||
|
||
pBuf = ( (PUCHAR) &pRequest->LineDevCaps ) + pRequest->LineDevCaps.ulProviderInfoOffset;
|
||
|
||
NdisMoveMemory( pBuf , TAPI_PROVIDER_STRING, sizeof( TAPI_PROVIDER_STRING ) );
|
||
|
||
//
|
||
// Tack on the LineName after the ProviderString
|
||
//
|
||
pRequest->LineDevCaps.ulLineNameSize = ( sizeof( TAPI_LINE_NAME ) - 1 ) + sizeof( TAPI_LINE_NUM );
|
||
|
||
pRequest->LineDevCaps.ulLineNameOffset = pRequest->LineDevCaps.ulProviderInfoOffset +
|
||
pRequest->LineDevCaps.ulProviderInfoSize;
|
||
|
||
pBuf = ( (PUCHAR) &pRequest->LineDevCaps ) + pRequest->LineDevCaps.ulLineNameOffset;
|
||
|
||
NdisMoveMemory( pBuf , TAPI_LINE_NAME, sizeof( TAPI_LINE_NAME ) );
|
||
|
||
//
|
||
// Tack on the line enumeration index at the end of the LineName
|
||
//
|
||
ulDeviceId = (ULONG) hdLine;
|
||
|
||
//
|
||
// Subtract 2: 1 for '\0' and 1 to adjust for array indexing
|
||
//
|
||
i = ( sizeof( TAPI_LINE_NUM ) / sizeof( CHAR ) ) - 2;
|
||
|
||
while ( i >= 0 && ( ulDeviceId > 0 ) )
|
||
{
|
||
szTapiLineNum[i] = (UCHAR)( ( ulDeviceId % 10 ) + '0' );
|
||
ulDeviceId /= 10;
|
||
i--;
|
||
}
|
||
|
||
pBuf += ( sizeof( TAPI_LINE_NAME ) - 1 );
|
||
|
||
NdisMoveMemory( pBuf, szTapiLineNum, sizeof( TAPI_LINE_NUM ) );
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpGetCallStatus(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_GET_CALL_STATUS pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request returns detailed information about the specified call.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_GET_CALL_STATUS
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_CALL hdCall;
|
||
OUT LINE_CALL_STATUS LineCallStatus;
|
||
|
||
} NDIS_TAPI_GET_CALL_STATUS, *PNDIS_TAPI_GET_CALL_STATUS;
|
||
|
||
typedef struct _LINE_CALL_STATUS
|
||
{
|
||
ULONG ulTotalSize;
|
||
ULONG ulNeededSize;
|
||
ULONG ulUsedSize;
|
||
|
||
ULONG ulCallState;
|
||
ULONG ulCallStateMode;
|
||
ULONG ulCallPrivilege;
|
||
ULONG ulCallFeatures;
|
||
|
||
ULONG ulDevSpecificSize;
|
||
ULONG ulDevSpecificOffset;
|
||
|
||
} LINE_CALL_STATUS, *PLINE_CALL_STATUS;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_FAILURE
|
||
NDIS_STATUS_TAPI_INVALCALLHANDLE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
CALL* pCall = NULL;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpGetCallStatus") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpGetCallStatus: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(NDIS_HANDLE) pRequest->hdCall );
|
||
|
||
if ( pCall == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_TAPI_INVALCALLHANDLE) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
||
}
|
||
|
||
pRequest->LineCallStatus.ulNeededSize = sizeof( LINE_CALL_STATUS );
|
||
|
||
if ( pRequest->LineCallStatus.ulTotalSize < pRequest->LineCallStatus.ulNeededSize )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_INVALID_LENGTH) );
|
||
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
pRequest->LineCallStatus.ulUsedSize = pRequest->LineCallStatus.ulNeededSize;
|
||
|
||
pRequest->LineCallStatus.ulCallFeatures = LINECALLFEATURE_ANSWER | LINECALLFEATURE_DROP;
|
||
pRequest->LineCallStatus.ulCallPrivilege = LINECALLPRIVILEGE_OWNER;
|
||
pRequest->LineCallStatus.ulCallState = pCall->ulTapiCallState;
|
||
|
||
switch ( pRequest->LineCallStatus.ulCallState )
|
||
{
|
||
case LINECALLSTATE_DIALTONE:
|
||
|
||
pRequest->LineCallStatus.ulCallStateMode = LINEDIALTONEMODE_NORMAL;
|
||
|
||
break;
|
||
|
||
case LINECALLSTATE_BUSY:
|
||
|
||
pRequest->LineCallStatus.ulCallStateMode = LINEBUSYMODE_STATION;
|
||
break;
|
||
|
||
case LINECALLSTATE_DISCONNECTED:
|
||
|
||
pRequest->LineCallStatus.ulCallStateMode = LINEDISCONNECTMODE_UNKNOWN;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// As we return the MAC addresses for caller and called station id's
|
||
// we set their size as 7 although a MAC address occupies 6 bytes.
|
||
// This is because TAPI overwrites the last bytes we return in these
|
||
// strings with a NULL character destroying the vaulable data.
|
||
// See bug: 313295
|
||
//
|
||
#define TAPI_STATION_ID_SIZE ( 7 * sizeof( CHAR ) )
|
||
|
||
NDIS_STATUS
|
||
TpGetCallInfo(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_GET_CALL_INFO pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request returns detailed information about the specified call.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_GET_CALL_INFO
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_CALL hdCall;
|
||
OUT LINE_CALL_INFO LineCallInfo;
|
||
|
||
} NDIS_TAPI_GET_CALL_INFO, *PNDIS_TAPI_GET_CALL_INFO;
|
||
|
||
typedef struct _LINE_CALL_INFO
|
||
{
|
||
ULONG ulTotalSize;
|
||
ULONG ulNeededSize;
|
||
ULONG ulUsedSize;
|
||
|
||
ULONG hLine;
|
||
ULONG ulLineDeviceID;
|
||
ULONG ulAddressID;
|
||
|
||
ULONG ulBearerMode;
|
||
ULONG ulRate;
|
||
ULONG ulMediaMode;
|
||
|
||
ULONG ulAppSpecific;
|
||
ULONG ulCallID;
|
||
ULONG ulRelatedCallID;
|
||
ULONG ulCallParamFlags;
|
||
ULONG ulCallStates;
|
||
|
||
ULONG ulMonitorDigitModes;
|
||
ULONG ulMonitorMediaModes;
|
||
LINE_DIAL_PARAMS DialParams;
|
||
|
||
ULONG ulOrigin;
|
||
ULONG ulReason;
|
||
ULONG ulCompletionID;
|
||
ULONG ulNumOwners;
|
||
ULONG ulNumMonitors;
|
||
|
||
ULONG ulCountryCode;
|
||
ULONG ulTrunk;
|
||
|
||
ULONG ulCallerIDFlags;
|
||
ULONG ulCallerIDSize;
|
||
ULONG ulCallerIDOffset;
|
||
ULONG ulCallerIDNameSize;
|
||
ULONG ulCallerIDNameOffset;
|
||
|
||
ULONG ulCalledIDFlags;
|
||
ULONG ulCalledIDSize;
|
||
ULONG ulCalledIDOffset;
|
||
ULONG ulCalledIDNameSize;
|
||
ULONG ulCalledIDNameOffset;
|
||
|
||
ULONG ulConnectedIDFlags;
|
||
ULONG ulConnectedIDSize;
|
||
ULONG ulConnectedIDOffset;
|
||
ULONG ulConnectedIDNameSize;
|
||
ULONG ulConnectedIDNameOffset;
|
||
|
||
ULONG ulRedirectionIDFlags;
|
||
ULONG ulRedirectionIDSize;
|
||
ULONG ulRedirectionIDOffset;
|
||
ULONG ulRedirectionIDNameSize;
|
||
ULONG ulRedirectionIDNameOffset;
|
||
|
||
ULONG ulRedirectingIDFlags;
|
||
ULONG ulRedirectingIDSize;
|
||
ULONG ulRedirectingIDOffset;
|
||
ULONG ulRedirectingIDNameSize;
|
||
ULONG ulRedirectingIDNameOffset;
|
||
|
||
ULONG ulAppNameSize;
|
||
ULONG ulAppNameOffset;
|
||
|
||
ULONG ulDisplayableAddressSize;
|
||
ULONG ulDisplayableAddressOffset;
|
||
|
||
ULONG ulCalledPartySize;
|
||
ULONG ulCalledPartyOffset;
|
||
|
||
ULONG ulCommentSize;
|
||
ULONG ulCommentOffset;
|
||
|
||
ULONG ulDisplaySize;
|
||
ULONG ulDisplayOffset;
|
||
|
||
ULONG ulUserUserInfoSize;
|
||
ULONG ulUserUserInfoOffset;
|
||
|
||
ULONG ulHighLevelCompSize;
|
||
ULONG ulHighLevelCompOffset;
|
||
|
||
ULONG ulLowLevelCompSize;
|
||
ULONG ulLowLevelCompOffset;
|
||
|
||
ULONG ulChargingInfoSize;
|
||
ULONG ulChargingInfoOffset;
|
||
|
||
ULONG ulTerminalModesSize;
|
||
ULONG ulTerminalModesOffset;
|
||
|
||
ULONG ulDevSpecificSize;
|
||
ULONG ulDevSpecificOffset;
|
||
|
||
} LINE_CALL_INFO, *PLINE_CALL_INFO;
|
||
|
||
typedef struct _LINE_DIAL_PARAMS
|
||
{
|
||
ULONG ulDialPause;
|
||
ULONG ulDialSpeed;
|
||
ULONG ulDigitDuration;
|
||
ULONG ulWaitForDialtone;
|
||
|
||
} LINE_DIAL_PARAMS, *PLINE_DIAL_PARAMS;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_FAILURE
|
||
NDIS_STATUS_TAPI_INVALCALLHANDLE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
CALL* pCall = NULL;
|
||
PLINE_CALL_INFO pLineCallInfo = NULL;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpGetCallInfo") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpGetCallInfo: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
pLineCallInfo = &pRequest->LineCallInfo;
|
||
|
||
pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(NDIS_HANDLE) pRequest->hdCall );
|
||
|
||
if ( pCall == NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_TAPI_INVALCALLHANDLE) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
||
}
|
||
|
||
pLineCallInfo->ulNeededSize = sizeof( LINE_CALL_INFO ) +
|
||
TAPI_STATION_ID_SIZE +
|
||
TAPI_STATION_ID_SIZE;
|
||
|
||
if ( pLineCallInfo->ulTotalSize < pLineCallInfo->ulNeededSize )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_INVALID_LENGTH) );
|
||
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
pLineCallInfo->ulUsedSize = pLineCallInfo->ulNeededSize;
|
||
|
||
pLineCallInfo->ulLineDeviceID = (ULONG) pCall->pLine->hdLine +
|
||
pCall->pLine->pAdapter->TapiProv.ulDeviceIDBase;
|
||
pLineCallInfo->ulAddressID = 0;
|
||
|
||
pLineCallInfo->ulBearerMode = LINEBEARERMODE_DATA;
|
||
pLineCallInfo->ulRate = pCall->ulSpeed;
|
||
pLineCallInfo->ulMediaMode = LINEMEDIAMODE_DIGITALDATA;
|
||
|
||
pLineCallInfo->ulCallParamFlags = LINECALLPARAMFLAGS_IDLE;
|
||
pLineCallInfo->ulCallStates = TAPI_LINECALLSTATES_SUPPORTED;
|
||
|
||
pLineCallInfo->ulCallerIDFlags = LINECALLPARTYID_UNAVAIL;
|
||
pLineCallInfo->ulCallerIDSize = 0;
|
||
pLineCallInfo->ulCalledIDOffset = 0;
|
||
pLineCallInfo->ulCalledIDFlags = LINECALLPARTYID_UNAVAIL;
|
||
pLineCallInfo->ulCalledIDSize = 0;
|
||
|
||
//
|
||
// Set the caller and called station id information for both
|
||
// incoming and outgoing calls.
|
||
//
|
||
{
|
||
CHAR *pBuf = NULL;
|
||
|
||
//
|
||
// Copy the caller id information
|
||
//
|
||
pLineCallInfo->ulCallerIDFlags = LINECALLPARTYID_ADDRESS;
|
||
pLineCallInfo->ulCallerIDSize = TAPI_STATION_ID_SIZE;
|
||
pLineCallInfo->ulCallerIDOffset = sizeof(LINE_CALL_INFO);
|
||
|
||
pBuf = ( (PUCHAR) pLineCallInfo ) + pLineCallInfo->ulCallerIDOffset;
|
||
NdisMoveMemory( pBuf, pCall->DestAddr, TAPI_STATION_ID_SIZE );
|
||
|
||
//
|
||
// Copy the called id information
|
||
//
|
||
pLineCallInfo->ulCalledIDFlags = LINECALLPARTYID_ADDRESS;
|
||
pLineCallInfo->ulCalledIDSize = TAPI_STATION_ID_SIZE;
|
||
pLineCallInfo->ulCalledIDOffset = pLineCallInfo->ulCallerIDOffset +
|
||
pLineCallInfo->ulCallerIDSize;
|
||
|
||
pBuf = ( (PUCHAR) pLineCallInfo ) + pLineCallInfo->ulCalledIDOffset;
|
||
NdisMoveMemory( pBuf, pCall->SrcAddr, TAPI_STATION_ID_SIZE );
|
||
|
||
pLineCallInfo->ulUsedSize = pLineCallInfo->ulNeededSize;
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
#define TAPI_LINE_ADDR_STRING "PPPoE VPN"
|
||
|
||
NDIS_STATUS
|
||
TpGetAddressCaps(
|
||
IN ADAPTER* pAdapter,
|
||
PNDIS_TAPI_GET_ADDRESS_CAPS pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request queries the specified address on the specified line device
|
||
to determine its telephony capabilities.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer ot our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_GET_ADDRESS_CAPS
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN ULONG ulDeviceID;
|
||
IN ULONG ulAddressID;
|
||
IN ULONG ulExtVersion;
|
||
OUT LINE_ADDRESS_CAPS LineAddressCaps;
|
||
|
||
} NDIS_TAPI_GET_ADDRESS_CAPS, *PNDIS_TAPI_GET_ADDRESS_CAPS;
|
||
|
||
typedef struct _LINE_ADDRESS_CAPS
|
||
{
|
||
ULONG ulTotalSize;
|
||
ULONG ulNeededSize;
|
||
ULONG ulUsedSize;
|
||
|
||
ULONG ulLineDeviceID;
|
||
|
||
ULONG ulAddressSize;
|
||
ULONG ulAddressOffset;
|
||
|
||
ULONG ulDevSpecificSize;
|
||
ULONG ulDevSpecificOffset;
|
||
|
||
ULONG ulAddressSharing;
|
||
ULONG ulAddressStates;
|
||
ULONG ulCallInfoStates;
|
||
ULONG ulCallerIDFlags;
|
||
ULONG ulCalledIDFlags;
|
||
ULONG ulConnectedIDFlags;
|
||
ULONG ulRedirectionIDFlags;
|
||
ULONG ulRedirectingIDFlags;
|
||
ULONG ulCallStates;
|
||
ULONG ulDialToneModes;
|
||
ULONG ulBusyModes;
|
||
ULONG ulSpecialInfo;
|
||
ULONG ulDisconnectModes;
|
||
|
||
ULONG ulMaxNumActiveCalls;
|
||
ULONG ulMaxNumOnHoldCalls;
|
||
ULONG ulMaxNumOnHoldPendingCalls;
|
||
ULONG ulMaxNumConference;
|
||
ULONG ulMaxNumTransConf;
|
||
|
||
ULONG ulAddrCapFlags;
|
||
ULONG ulCallFeatures;
|
||
ULONG ulRemoveFromConfCaps;
|
||
ULONG ulRemoveFromConfState;
|
||
ULONG ulTransferModes;
|
||
|
||
ULONG ulForwardModes;
|
||
ULONG ulMaxForwardEntries;
|
||
ULONG ulMaxSpecificEntries;
|
||
ULONG ulMinFwdNumRings;
|
||
ULONG ulMaxFwdNumRings;
|
||
|
||
ULONG ulMaxCallCompletions;
|
||
ULONG ulCallCompletionConds;
|
||
ULONG ulCallCompletionModes;
|
||
ULONG ulNumCompletionMessages;
|
||
ULONG ulCompletionMsgTextEntrySize;
|
||
ULONG ulCompletionMsgTextSize;
|
||
ULONG ulCompletionMsgTextOffset;
|
||
|
||
} LINE_ADDRESS_CAPS, *PLINE_ADDRESS_CAPS;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_TAPI_INVALADDRESSID
|
||
NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION
|
||
NDIS_STATUS_TAPI_NODRIVER
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
HDRV_LINE hdLine = INVALID_LINE_HANDLE;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpGetAddressCaps") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpGetAddressCaps: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
//
|
||
// Retrieve the handle to line context
|
||
//
|
||
hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
|
||
|
||
if ( hdLine == INVALID_LINE_HANDLE )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_NODRIVER) );
|
||
|
||
return NDIS_STATUS_TAPI_NODRIVER;
|
||
}
|
||
|
||
//
|
||
// Verify the address id
|
||
//
|
||
if ( pRequest->ulAddressID != 0 )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_INVALADDRESSID) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALADDRESSID;
|
||
}
|
||
|
||
//
|
||
// Verify the extension versions
|
||
//
|
||
if ( pRequest->ulExtVersion != 0 &&
|
||
pRequest->ulExtVersion != TAPI_EXT_VERSION)
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION) );
|
||
|
||
return NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION;
|
||
}
|
||
|
||
pRequest->LineAddressCaps.ulNeededSize = sizeof( LINE_ADDRESS_CAPS ) +
|
||
sizeof( TAPI_LINE_ADDR_STRING );
|
||
|
||
if ( pRequest->LineAddressCaps.ulTotalSize < pRequest->LineAddressCaps.ulNeededSize )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_INVALID_LENGTH) );
|
||
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
pRequest->LineAddressCaps.ulUsedSize = pRequest->LineAddressCaps.ulNeededSize;
|
||
|
||
pRequest->LineAddressCaps.ulDialToneModes = LINEDIALTONEMODE_NORMAL;
|
||
|
||
pRequest->LineAddressCaps.ulSpecialInfo = LINESPECIALINFO_UNAVAIL;
|
||
|
||
pRequest->LineAddressCaps.ulDisconnectModes = LINEDISCONNECTMODE_NORMAL |
|
||
LINEDISCONNECTMODE_UNKNOWN |
|
||
LINEDISCONNECTMODE_BUSY |
|
||
LINEDISCONNECTMODE_NOANSWER |
|
||
LINEDISCONNECTMODE_UNREACHABLE |
|
||
LINEDISCONNECTMODE_BADADDRESS |
|
||
LINEDISCONNECTMODE_INCOMPATIBLE |
|
||
LINEDISCONNECTMODE_REJECT |
|
||
LINEDISCONNECTMODE_NODIALTONE;
|
||
|
||
pRequest->LineAddressCaps.ulMaxNumActiveCalls = pAdapter->nCallsPerLine;
|
||
|
||
pRequest->LineAddressCaps.ulMaxNumTransConf = 1;
|
||
pRequest->LineAddressCaps.ulAddrCapFlags = LINEADDRCAPFLAGS_DIALED;
|
||
|
||
pRequest->LineAddressCaps.ulCallFeatures = LINECALLFEATURE_ACCEPT |
|
||
LINECALLFEATURE_ANSWER |
|
||
LINECALLFEATURE_COMPLETECALL |
|
||
LINECALLFEATURE_DIAL |
|
||
LINECALLFEATURE_DROP;
|
||
|
||
pRequest->LineAddressCaps.ulLineDeviceID = pRequest->ulDeviceID;
|
||
pRequest->LineAddressCaps.ulAddressSharing = LINEADDRESSSHARING_PRIVATE;
|
||
pRequest->LineAddressCaps.ulAddressStates = 0;
|
||
|
||
//
|
||
// List of all possible call states.
|
||
//
|
||
pRequest->LineAddressCaps.ulCallStates = TAPI_LINECALLSTATES_SUPPORTED;
|
||
|
||
pRequest->LineAddressCaps.ulAddressSize = sizeof( TAPI_LINE_ADDR_STRING );
|
||
pRequest->LineAddressCaps.ulAddressOffset = sizeof( LINE_ADDRESS_CAPS );
|
||
|
||
{
|
||
CHAR* pBuf;
|
||
|
||
pBuf = ( (PUCHAR) &pRequest->LineAddressCaps ) + sizeof( LINE_ADDRESS_CAPS );
|
||
NdisMoveMemory( pBuf, TAPI_LINE_ADDR_STRING, sizeof( TAPI_LINE_ADDR_STRING ) );
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpSetStatusMessages(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_SET_STATUS_MESSAGES pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request enables the Connection Wrapper to specify which notification
|
||
messages the miniport should generate for events related to status changes
|
||
for the specified line or any of its addresses. By default, address and
|
||
line status reporting is initially disabled for a line.
|
||
|
||
Parameters:
|
||
|
||
pAdapter _ A pointer to our adapter information structure.
|
||
|
||
pRequest _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_SET_STATUS_MESSAGES
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_LINE hdLine;
|
||
IN ULONG ulLineStates;
|
||
IN ULONG ulAddressStates;
|
||
|
||
} NDIS_TAPI_SET_STATUS_MESSAGES, *PNDIS_TAPI_SET_STATUS_MESSAGES;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_TAPI_INVALLINEHANDLE
|
||
NDIS_STATUS_TAPI_INVALLINESTATE
|
||
NDIS_STATUS_TAPI_INVALADDRESSSTATE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpSetStatusMessages") );
|
||
//
|
||
// We do not send any line or address state change notifications at all,
|
||
// so we do not care about it.
|
||
//
|
||
// We care about call notification messages and they are always on by default.
|
||
//
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpSetStatusMessages=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
VOID
|
||
TpCallStateChangeHandler(
|
||
IN CALL* pCall,
|
||
IN ULONG ulCallState,
|
||
IN ULONG ulStateParam
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This routine will indicate the given LINECALLSTATE to the Connection
|
||
wrapper if the event has been enabled by the wrapper. Otherwise the state
|
||
information is saved, but no indication is made.
|
||
|
||
|
||
LINECALLSTATE_ Constants: The LINECALLSTATE_ bit-flag constants describe the
|
||
call states a call can be in.
|
||
|
||
LINECALLSTATE_ACCEPTED:
|
||
The call was in the offering state and has been accepted. This indicates to
|
||
other (monitoring) applications that the current owner application has
|
||
claimed responsibility for answering the call. In ISDN, the accepted state is
|
||
entered when the called-party equipment sends a message to the switch
|
||
indicating that it is willing to present the call to the called person. This
|
||
has the side effect of alerting (ringing) the users at both ends of the call.
|
||
An incoming call can always be immediately answered without first being
|
||
separately accepted.
|
||
|
||
LINECALLSTATE_BUSY
|
||
The call is receiving a busy tone. A busy tone indicates that the call cannot
|
||
be completed either a circuit (trunk) or the remote party's station are in use
|
||
. See LINEBUSYMODE_ Constants.
|
||
|
||
LINECALLSTATE_CONFERENCED
|
||
The call is a member of a conference call and is logically in the connected
|
||
state.
|
||
|
||
LINECALLSTATE_CONNECTED
|
||
The call has been established and the connection is made. Information is able
|
||
to flow over the call between the originating address and the destination
|
||
address.
|
||
|
||
LINECALLSTATE_DIALING
|
||
The originator is dialing digits on the call. The dialed digits are collected
|
||
by the switch. Note that neither lineGenerateDigits nor
|
||
TSPI_lineGenerateDigits will place the line into the dialing state.
|
||
|
||
LINECALLSTATE_DIALTONE
|
||
The call is receiving a dial tone from the switch, which means that the
|
||
switch is ready to receive a dialed number. See LINEDIALTONEMODE_ Constants
|
||
for identifiers of special dial tones, such as a stutter tone of normal voice
|
||
mail.
|
||
|
||
LINECALLSTATE_DISCONNECTED
|
||
The remote party has disconnected from the call.
|
||
|
||
LINECALLSTATE_IDLE
|
||
The call exists but has not been connected. No activity exists on the call,
|
||
which means that no call is currently active. A call can never transition
|
||
into the idle state.
|
||
|
||
LINECALLSTATE_OFFERING
|
||
The call is being offered to the station, signaling the arrival of a new call
|
||
. The offering state is not the same as causing a phone or computer to ring.
|
||
In some environments, a call in the offering state does not ring the user
|
||
until the switch instructs the line to ring. An example use might be where an
|
||
incoming call appears on several station sets but only the primary address
|
||
rings. The instruction to ring does not affect any call states.
|
||
|
||
LINECALLSTATE_ONHOLD
|
||
The call is on hold by the switch. This frees the physical line, which allows
|
||
another call to use the line.
|
||
|
||
LINECALLSTATE_ONHOLDPENDCONF
|
||
The call is currently on hold while it is being added to a conference.
|
||
|
||
LINECALLSTATE_ONHOLDPENDTRANSFER
|
||
The call is currently on hold awaiting transfer to another number.
|
||
|
||
LINECALLSTATE_PROCEEDING
|
||
Dialing has completed and the call is proceeding through the switch or
|
||
telephone network. This occurs after dialing is complete and before the call
|
||
reaches the dialed party, as indicated by ringback, busy, or answer.
|
||
|
||
LINECALLSTATE_RINGBACK
|
||
The station to be called has been reached, and the destination's switch is
|
||
generating a ring tone back to the originator. A ringback means that the
|
||
destination address is being alerted to the call.
|
||
|
||
LINECALLSTATE_SPECIALINFO
|
||
The call is receiving a special information signal, which precedes a
|
||
prerecorded announcement indicating why a call cannot be completed. See
|
||
LINESPECIALINFO_ Constants.
|
||
|
||
LINECALLSTATE_UNKNOWN
|
||
The call exists, but its state is currently unknown. This may be the result
|
||
of poor call progress detection by the service provider. A call state message
|
||
with the call state set to unknown may also be generated to inform the TAPI
|
||
DLL about a new call at a time when the actual call state of the call is not
|
||
exactly known.
|
||
|
||
Parameters:
|
||
|
||
pCall _ A pointer to our call information structure.
|
||
|
||
ulCallState _ The LINECALLSTATE event to be posted to TAPI/WAN.
|
||
|
||
ulStateParam _ This value depends on the event being posted, and some
|
||
events will pass in zero if they don't use this parameter.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
BOOLEAN fIndicateStatus = FALSE;
|
||
NDIS_TAPI_EVENT TapiEvent;
|
||
ULONG ulOldCallState;
|
||
|
||
ASSERT( VALIDATE_CALL( pCall ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpCallStateChangeHandler") );
|
||
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
do
|
||
{
|
||
//
|
||
// Check if we have a valid htCall member, otherwise it means we are already done,
|
||
// so we should not give any more notifications to TAPI about state changes
|
||
//
|
||
if ( pCall->htCall == (HTAPI_CALL) NULL )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: No valid htCall") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// A connect notification can come only after a PROCEEDING or OFFERING state
|
||
// is reached
|
||
//
|
||
if ( ulCallState == LINECALLSTATE_CONNECTED &&
|
||
( pCall->ulTapiCallState != LINECALLSTATE_OFFERING &&
|
||
pCall->ulTapiCallState != LINECALLSTATE_PROCEEDING ) )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: Invalid order of state change") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If the new state is the same as old state, just return
|
||
//
|
||
if ( pCall->ulTapiCallState == ulCallState )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: No state change") );
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Otherwise, change the calls state, and
|
||
// make a notification to TAPI about the new state
|
||
//
|
||
ulOldCallState = pCall->ulTapiCallState;
|
||
pCall->ulTapiCallState = ulCallState;
|
||
|
||
TapiEvent.htLine = pCall->pLine->htLine;
|
||
TapiEvent.htCall = pCall->htCall;
|
||
|
||
TapiEvent.ulMsg = LINE_CALLSTATE;
|
||
|
||
TapiEvent.ulParam1 = ulCallState;
|
||
TapiEvent.ulParam2 = ulStateParam;
|
||
TapiEvent.ulParam3 = LINEMEDIAMODE_DIGITALDATA;
|
||
|
||
fIndicateStatus = TRUE;
|
||
|
||
if ( ulCallState == LINECALLSTATE_CONNECTED )
|
||
{
|
||
ADAPTER* pAdapter = pCall->pLine->pAdapter;
|
||
|
||
//
|
||
// Since the call is connected, reset CLBF_CallConnectPending bit
|
||
//
|
||
pCall->ulClFlags &= ~CLBF_CallConnectPending;
|
||
|
||
//
|
||
// Also prepare the WanLinkInfo structure of call context now
|
||
// as right after we indicate line-up to NDISWAN, it will query us
|
||
// for this info.
|
||
//
|
||
NdisZeroMemory( &pCall->NdisWanLinkInfo, sizeof( pCall->NdisWanLinkInfo ) );
|
||
|
||
pCall->NdisWanLinkInfo.MaxSendFrameSize = pCall->ulMaxFrameSize;
|
||
pCall->NdisWanLinkInfo.MaxRecvFrameSize = pCall->ulMaxFrameSize;
|
||
|
||
pCall->NdisWanLinkInfo.HeaderPadding = pAdapter->NdisWanInfo.HeaderPadding;
|
||
pCall->NdisWanLinkInfo.TailPadding = pAdapter->NdisWanInfo.TailPadding;
|
||
|
||
pCall->NdisWanLinkInfo.SendFramingBits = pAdapter->NdisWanInfo.FramingBits;
|
||
pCall->NdisWanLinkInfo.RecvFramingBits = pAdapter->NdisWanInfo.FramingBits;
|
||
|
||
pCall->NdisWanLinkInfo.SendACCM = 0;
|
||
pCall->NdisWanLinkInfo.RecvACCM = 0;
|
||
|
||
}
|
||
else if ( ulCallState == LINECALLSTATE_DISCONNECTED )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: LINEDISCONNECTMODE: %x", ulStateParam ) );
|
||
|
||
//
|
||
// This state change will only occur if TpDropCall() is in progress,
|
||
// so we invalidate the htCall member of call context in order to prevent
|
||
// a possible out of sync state change notification.
|
||
//
|
||
pCall->htCall = (HTAPI_CALL) NULL;
|
||
|
||
}
|
||
|
||
} while ( FALSE) ;
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
//
|
||
// Notify state change to TAPI if needed
|
||
//
|
||
if ( fIndicateStatus )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: Indicate LINE_CALLSTATE change: %x -> %x",ulOldCallState,ulCallState ) );
|
||
|
||
NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_TAPI_INDICATION,
|
||
&TapiEvent,
|
||
sizeof( NDIS_TAPI_EVENT ) );
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpCallStateChangeHandler") );
|
||
}
|
||
|
||
|
||
NDIS_STATUS
|
||
TpMakeCall(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_MAKE_CALL pRequest,
|
||
IN ULONG ulRequestLength
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request places a call on the specified line to the specified
|
||
destination address. Optionally, call parameters can be specified if
|
||
anything but default call setup parameters are requested.
|
||
|
||
Parameters:
|
||
|
||
Adapter _ A pointer ot our adapter information structure.
|
||
|
||
Request _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_MAKE_CALL
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_LINE hdLine;
|
||
IN HTAPI_CALL htCall;
|
||
OUT HDRV_CALL hdCall;
|
||
IN ULONG ulDestAddressSize;
|
||
IN ULONG ulDestAddressOffset;
|
||
IN BOOLEAN bUseDefaultLineCallParams;
|
||
IN LINE_CALL_PARAMS LineCallParams;
|
||
|
||
} NDIS_TAPI_MAKE_CALL, *PNDIS_TAPI_MAKE_CALL;
|
||
|
||
typedef struct _LINE_CALL_PARAMS // Defaults:
|
||
{
|
||
ULONG ulTotalSize; // ---------
|
||
|
||
ULONG ulBearerMode; // voice
|
||
ULONG ulMinRate; // (3.1kHz)
|
||
ULONG ulMaxRate; // (3.1kHz)
|
||
ULONG ulMediaMode; // interactiveVoice
|
||
|
||
ULONG ulCallParamFlags; // 0
|
||
ULONG ulAddressMode; // addressID
|
||
ULONG ulAddressID; // (any available)
|
||
|
||
LINE_DIAL_PARAMS DialParams; // (0, 0, 0, 0)
|
||
|
||
ULONG ulOrigAddressSize; // 0
|
||
ULONG ulOrigAddressOffset;
|
||
ULONG ulDisplayableAddressSize;
|
||
ULONG ulDisplayableAddressOffset;
|
||
|
||
ULONG ulCalledPartySize; // 0
|
||
ULONG ulCalledPartyOffset;
|
||
|
||
ULONG ulCommentSize; // 0
|
||
ULONG ulCommentOffset;
|
||
|
||
ULONG ulUserUserInfoSize; // 0
|
||
ULONG ulUserUserInfoOffset;
|
||
|
||
ULONG ulHighLevelCompSize; // 0
|
||
ULONG ulHighLevelCompOffset;
|
||
|
||
ULONG ulLowLevelCompSize; // 0
|
||
ULONG ulLowLevelCompOffset;
|
||
|
||
ULONG ulDevSpecificSize; // 0
|
||
ULONG ulDevSpecificOffset;
|
||
|
||
} LINE_CALL_PARAMS, *PLINE_CALL_PARAMS;
|
||
|
||
typedef struct _LINE_DIAL_PARAMS
|
||
{
|
||
ULONG ulDialPause;
|
||
ULONG ulDialSpeed;
|
||
ULONG ulDigitDuration;
|
||
ULONG ulWaitForDialtone;
|
||
|
||
} LINE_DIAL_PARAMS, *PLINE_DIAL_PARAMS;
|
||
|
||
RequestLength _ Length of the request buffer
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_TAPI_ADDRESSBLOCKED
|
||
NDIS_STATUS_TAPI_BEARERMODEUNAVAIL
|
||
NDIS_STATUS_TAPI_CALLUNAVAIL
|
||
NDIS_STATUS_TAPI_DIALBILLING
|
||
NDIS_STATUS_TAPI_DIALQUIET
|
||
NDIS_STATUS_TAPI_DIALDIALTONE
|
||
NDIS_STATUS_TAPI_DIALPROMPT
|
||
NDIS_STATUS_TAPI_INUSE
|
||
NDIS_STATUS_TAPI_INVALADDRESSMODE
|
||
NDIS_STATUS_TAPI_INVALBEARERMODE
|
||
NDIS_STATUS_TAPI_INVALMEDIAMODE
|
||
NDIS_STATUS_TAPI_INVALLINESTATE
|
||
NDIS_STATUS_TAPI_INVALRATE
|
||
NDIS_STATUS_TAPI_INVALLINEHANDLE
|
||
NDIS_STATUS_TAPI_INVALADDRESS
|
||
NDIS_STATUS_TAPI_INVALADDRESSID
|
||
NDIS_STATUS_TAPI_INVALCALLPARAMS
|
||
NDIS_STATUS_RESOURCES
|
||
NDIS_STATUS_TAPI_OPERATIONUNAVAIL
|
||
NDIS_STATUS_FAILURE
|
||
NDIS_STATUS_TAPI_RESOURCEUNAVAIL
|
||
NDIS_STATUS_TAPI_RATEUNAVAIL
|
||
NDIS_STATUS_TAPI_USERUSERINFOTOOBIG
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
||
LINE* pLine = NULL;
|
||
|
||
CALL* pCall = NULL;
|
||
HDRV_CALL hdCall = (HDRV_CALL) NULL;
|
||
|
||
BOOLEAN fCallInsertedToHandleTable = FALSE;
|
||
|
||
WORKITEM* pWorkItem = NULL;
|
||
PVOID Args[4];
|
||
|
||
BOOLEAN fRenumerationNotScheduled = FALSE;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpMakeCall") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpMakeCall: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
//
|
||
// Retrieve a pointer to the line context
|
||
//
|
||
pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
|
||
|
||
if ( pLine == NULL )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALLINEHANDLE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// See if we can make calls on this line at all
|
||
//
|
||
if ( ! (pLine->ulLnFlags & LNBF_MakeOutgoingCalls ) )
|
||
{
|
||
status = NDIS_STATUS_TAPI_ADDRESSBLOCKED;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// See if we can still make calls on this line
|
||
//
|
||
if ( pLine->nActiveCalls == pLine->nMaxCalls )
|
||
{
|
||
status = NDIS_STATUS_TAPI_OPERATIONUNAVAIL;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Make sure the parameters suppied in the request are acceptable
|
||
//
|
||
if ( pRequest->bUseDefaultLineCallParams )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALCALLPARAMS;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
if ( !( pRequest->LineCallParams.ulBearerMode & LINEBEARERMODE_DATA ) )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALBEARERMODE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
if ( !( pRequest->LineCallParams.ulMediaMode & LINEMEDIAMODE_DIGITALDATA ) )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
if ( !( pRequest->LineCallParams.ulAddressMode &
|
||
( LINEADDRESSMODE_ADDRESSID | LINEADDRESSMODE_DIALABLEADDR ) ) )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALADDRESSMODE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
if ( pRequest->LineCallParams.ulAddressID > 0 )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALADDRESSID;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
if ( pRequest->ulDestAddressOffset + pRequest->ulDestAddressSize > ulRequestLength )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALPARAM;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
//
|
||
// Create a call context
|
||
//
|
||
if ( ALLOC_CALL( &pCall ) != NDIS_STATUS_SUCCESS )
|
||
{
|
||
status = NDIS_STATUS_RESOURCES;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
do
|
||
{
|
||
//
|
||
// Initialize the call context
|
||
//
|
||
status = TpCallInitialize( pCall, pLine, pRequest->htCall, FALSE /* fIncoming */ );
|
||
|
||
if ( status != NDIS_STATUS_SUCCESS )
|
||
break;
|
||
|
||
//
|
||
// Insert the call context into the tapi provider's handle table
|
||
//
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
hdCall = (HDRV_CALL) InsertToHandleTable( pAdapter->TapiProv.hCallTable,
|
||
NO_PREFERED_INDEX,
|
||
pCall );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
if ( hdCall == (HDRV_CALL) NULL )
|
||
{
|
||
status = NDIS_STATUS_TAPI_CALLUNAVAIL;
|
||
|
||
break;
|
||
}
|
||
|
||
fCallInsertedToHandleTable = TRUE;
|
||
|
||
//
|
||
// Set the call's hdCall member
|
||
//
|
||
pCall->hdCall = hdCall;
|
||
|
||
//
|
||
// Set AC Name and the service name passed in the request.
|
||
// We expect it in the following format:
|
||
// AC Name\Service Name
|
||
//
|
||
// The following examles are all valid:
|
||
// AC Name\ -> Connect to the default service on the specified AC
|
||
// Service Name -> Connect to the specified service on any AC
|
||
// AC Name\Service Name -> Connect to the specified service on the specified AC
|
||
// -> Connect to the default service on any AC
|
||
//
|
||
// We will also strip off any leading or trailing space chars.
|
||
//
|
||
|
||
{
|
||
CHAR* pBuf = ( (PUCHAR) pRequest ) + pRequest->ulDestAddressOffset;
|
||
ULONG size = pRequest->ulDestAddressSize;
|
||
|
||
ULONG ACNameStartPos, ACNameEndPos;
|
||
ULONG ServiceNameStartPos, ServiceNameEndPos;
|
||
|
||
//
|
||
// Remove the terminating NULL characters if passed any.
|
||
//
|
||
for ( ; size > 0 ; size-- )
|
||
{
|
||
if ( pBuf[ size - 1] != '\0' )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Get the AC Name and service name
|
||
//
|
||
do
|
||
{
|
||
ULONG i = 0;
|
||
CHAR* pTempChar = pBuf;
|
||
|
||
ACNameStartPos = ACNameEndPos = 0;
|
||
ServiceNameStartPos = ServiceNameEndPos = 0;
|
||
|
||
//
|
||
// Skip leading spaces
|
||
//
|
||
while (i < size)
|
||
{
|
||
if (*pTempChar != ' ')
|
||
{
|
||
break;
|
||
}
|
||
|
||
i++;
|
||
|
||
pTempChar++;
|
||
}
|
||
|
||
if (i == size)
|
||
{
|
||
break;
|
||
}
|
||
|
||
ACNameStartPos = ACNameEndPos = i;
|
||
|
||
while (i < size)
|
||
{
|
||
if (*pTempChar == '\\')
|
||
{
|
||
break;
|
||
}
|
||
|
||
i++;
|
||
|
||
if (*pTempChar != ' ')
|
||
{
|
||
//
|
||
// Mark the beginning of trailing spaces
|
||
//
|
||
ACNameEndPos = i;
|
||
}
|
||
|
||
pTempChar++;
|
||
}
|
||
|
||
if (i == size)
|
||
{
|
||
//
|
||
// No AC Name was specified, it was just Service Name
|
||
// and we parsed it
|
||
//
|
||
ServiceNameStartPos = ACNameStartPos;
|
||
ServiceNameEndPos = ACNameEndPos;
|
||
|
||
ACNameStartPos = ACNameEndPos = 0;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Advance 'i' and 'pTempChar' once to skip the '\' character
|
||
//
|
||
i++;
|
||
|
||
pTempChar++;
|
||
|
||
//
|
||
// Skip leading spaces
|
||
//
|
||
while (i < size)
|
||
{
|
||
if (*pTempChar != ' ')
|
||
{
|
||
break;
|
||
}
|
||
|
||
i++;
|
||
|
||
pTempChar++;
|
||
}
|
||
|
||
if (i == size)
|
||
{
|
||
break;
|
||
}
|
||
|
||
ServiceNameStartPos = ServiceNameEndPos = i;
|
||
|
||
while (i < size)
|
||
{
|
||
i++;
|
||
|
||
if (*pTempChar != ' ')
|
||
{
|
||
//
|
||
// Mark the beginning of trailing spaces
|
||
//
|
||
ServiceNameEndPos = i;
|
||
}
|
||
|
||
pTempChar++;
|
||
}
|
||
|
||
} while ( FALSE );
|
||
|
||
//
|
||
// Retrieve the AC Name information into the call context
|
||
//
|
||
pCall->nACNameLength = (USHORT) ( ( MAX_AC_NAME_LENGTH < ( ACNameEndPos - ACNameStartPos ) ) ?
|
||
MAX_AC_NAME_LENGTH : ( ACNameEndPos - ACNameStartPos ) );
|
||
|
||
|
||
if ( pCall->nACNameLength != 0 )
|
||
{
|
||
NdisMoveMemory( pCall->ACName, &pBuf[ACNameStartPos], pCall->nACNameLength );
|
||
|
||
pCall->fACNameSpecified = TRUE;
|
||
}
|
||
|
||
//
|
||
// Retrieve the Service Name information into the call context
|
||
//
|
||
pCall->nServiceNameLength = (USHORT) ( ( MAX_SERVICE_NAME_LENGTH < ( ServiceNameEndPos - ServiceNameStartPos ) ) ?
|
||
MAX_SERVICE_NAME_LENGTH : ( ServiceNameEndPos - ServiceNameStartPos ) );
|
||
|
||
|
||
if ( pCall->nServiceNameLength != 0 )
|
||
{
|
||
NdisMoveMemory( pCall->ServiceName, &pBuf[ServiceNameStartPos], pCall->nServiceNameLength );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Allocate a work item for scheduling FsmMakeCall()
|
||
//
|
||
// Set the arguements array
|
||
//
|
||
Args[0] = (PVOID) pCall;
|
||
|
||
pWorkItem = AllocWorkItem( &gl_llistWorkItems,
|
||
ExecAdapterWorkItem,
|
||
NULL,
|
||
Args,
|
||
CWT_workFsmMakeCall );
|
||
|
||
if ( pWorkItem == NULL )
|
||
{
|
||
status = NDIS_STATUS_RESOURCES;
|
||
|
||
break;
|
||
}
|
||
|
||
{
|
||
//
|
||
// Schedule a work item to reenumerate bindings
|
||
//
|
||
WORKITEM* pCallWorkItem;
|
||
|
||
Args[0] = (PVOID) BN_SetFiltersForMakeCall; // Is a set filter request
|
||
Args[1] = (PVOID) pCall;
|
||
Args[2] = (PVOID) pRequest;
|
||
Args[3] = (PVOID) pWorkItem;
|
||
|
||
pCallWorkItem = pWorkItem;
|
||
|
||
//
|
||
// Allocate work item for the bind
|
||
//
|
||
pWorkItem = AllocWorkItem( &gl_llistWorkItems,
|
||
ExecBindingWorkItem,
|
||
NULL,
|
||
Args,
|
||
BWT_workPrStartBinds );
|
||
|
||
if ( pWorkItem == NULL )
|
||
{
|
||
//
|
||
// We can not allocate the work item for reenumeration of bindings
|
||
// But may be all enumerations are intact, so let the
|
||
// make call request continue
|
||
//
|
||
|
||
pWorkItem = pCallWorkItem;
|
||
|
||
fRenumerationNotScheduled = TRUE;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Insert the call context into the line's active call list
|
||
//
|
||
NdisAcquireSpinLock( &pLine->lockLine );
|
||
|
||
InsertHeadList( &pLine->linkCalls, &pCall->linkCalls );
|
||
|
||
pLine->nActiveCalls++;
|
||
|
||
ReferenceLine( pLine, FALSE );
|
||
|
||
NdisReleaseSpinLock( &pLine->lockLine );
|
||
|
||
//
|
||
// Reference the call 3 times:
|
||
// 1. For scheduling of FsmMakeCall()
|
||
// 2. For dropping of the call
|
||
// 3. For closing of the call
|
||
//
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
ReferenceCall( pCall, FALSE );
|
||
ReferenceCall( pCall, FALSE );
|
||
ReferenceCall( pCall, FALSE );
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
//
|
||
// Schedule the bind operation
|
||
//
|
||
ScheduleWorkItem( pWorkItem );
|
||
|
||
status = NDIS_STATUS_SUCCESS;
|
||
|
||
} while ( FALSE );
|
||
|
||
if ( status == NDIS_STATUS_SUCCESS )
|
||
{
|
||
//
|
||
// If succesfull, return the call handle to TAPI and mark call as TAPI notified
|
||
// of new call
|
||
//
|
||
pRequest->hdCall = hdCall;
|
||
|
||
//
|
||
// If we have scheduled a reenumeration work item, then pend this request
|
||
// It will be completed when reenumeration is complete.
|
||
//
|
||
if ( !fRenumerationNotScheduled )
|
||
{
|
||
status = NDIS_STATUS_PENDING;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
//
|
||
// Somethings failed, do clean up
|
||
//
|
||
|
||
if ( fCallInsertedToHandleTable )
|
||
{
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
RemoveFromHandleTable( pAdapter->TapiProv.hCallTable, (NDIS_HANDLE) hdCall );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
}
|
||
|
||
if ( pCall )
|
||
{
|
||
TpCallCleanup( pCall );
|
||
}
|
||
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
VOID
|
||
TpMakeCallComplete(
|
||
IN CALL* pCall,
|
||
IN PNDIS_TAPI_MAKE_CALL pRequest
|
||
)
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("+TpMakeCallComplete") );
|
||
|
||
NdisMQueryInformationComplete( pCall->pLine->pAdapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_SUCCESS );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpMakeCallComplete=$%x",NDIS_STATUS_SUCCESS) );
|
||
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpCallInitialize(
|
||
IN CALL* pCall,
|
||
IN LINE* pLine,
|
||
IN HTAPI_CALL htCall,
|
||
IN BOOLEAN fIncoming
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function makes initialization on the call context.
|
||
|
||
Parameters:
|
||
|
||
pCall _ A pointer to our call information structure.
|
||
|
||
pLine _ A pointer to the line information structure that the call belongs.
|
||
|
||
htCall _ Handle assigned to the call by TAPI.
|
||
|
||
fIncoming _ Flag that indicates if the call is inbound or outbound.
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_FAILURE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpCallInitialize") );
|
||
|
||
NdisZeroMemory( pCall, sizeof( CALL ) );
|
||
|
||
InitializeListHead( &pCall->linkCalls );
|
||
|
||
pCall->tagCall = MTAG_CALL;
|
||
|
||
pCall->ulClFlags = ( CLBF_CallOpen | CLBF_CallConnectPending );
|
||
|
||
NdisAllocateSpinLock( &pCall->lockCall );
|
||
|
||
pCall->fIncoming = fIncoming;
|
||
|
||
pCall->pLine = pLine;
|
||
|
||
pCall->htCall = htCall;
|
||
|
||
InitializeListHead( &pCall->linkReceivedPackets );
|
||
|
||
pCall->ulTapiCallState = LINECALLSTATE_IDLE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpCallInitialize") );
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
TpAnswerCall(
|
||
IN ADAPTER* pAdapter,
|
||
IN PNDIS_TAPI_ANSWER pRequest
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This request answers the specified offering call. It may optionally send
|
||
the specified user-to-user information to the calling party.
|
||
|
||
Parameters:
|
||
|
||
Adapter _ A pointer ot our adapter information structure.
|
||
|
||
Request _ A pointer to the NDIS_TAPI request structure for this call.
|
||
|
||
typedef struct _NDIS_TAPI_ANSWER
|
||
{
|
||
IN ULONG ulRequestID;
|
||
IN HDRV_CALL hdCall;
|
||
IN ULONG ulUserUserInfoSize;
|
||
IN UCHAR UserUserInfo[1];
|
||
|
||
} NDIS_TAPI_ANSWER, *PNDIS_TAPI_ANSWER;
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_TAPI_INVALCALLHANDLE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
||
CALL* pCall = NULL;
|
||
|
||
ASSERT( VALIDATE_ADAPTER( pAdapter ) );
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpAnswerCall") );
|
||
|
||
if ( pRequest == NULL || pAdapter == NULL )
|
||
{
|
||
TRACE( TL_A, TM_Tp, ("TpAnswerCall: Invalid parameter") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpAnswerCall=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
|
||
|
||
return NDIS_STATUS_TAPI_INVALPARAM;
|
||
}
|
||
|
||
|
||
pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(NDIS_HANDLE) pRequest->hdCall );
|
||
|
||
if ( pCall == NULL )
|
||
{
|
||
status = NDIS_STATUS_TAPI_INVALCALLHANDLE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpAnswerCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
status = FsmAnswerCall( pCall );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpAnswerCall=$%x",status) );
|
||
|
||
return status;
|
||
}
|
||
|
||
VOID
|
||
ExecAdapterWorkItem(
|
||
IN PVOID Args[4],
|
||
IN UINT workType
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function executes the scheduled work items for the adapter.
|
||
|
||
|
||
Parameters:
|
||
|
||
Args:
|
||
An array of length 4 keeping PVOIDs
|
||
|
||
workType:
|
||
Indicates the type of the work to be executed.
|
||
We use this to understand what we should do in this function.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
|
||
TRACE( TL_N, TM_Mp, ("+ExecAdapterWorkItem") );
|
||
|
||
switch ( workType )
|
||
{
|
||
|
||
case CWT_workFsmMakeCall:
|
||
|
||
//
|
||
// Scheduled from TpMakeCall() to start an outgoing call
|
||
//
|
||
{
|
||
CALL* pCall = (CALL*) Args[0];
|
||
|
||
FsmMakeCall( pCall );
|
||
|
||
//
|
||
// Remove the reference due to scheduling of FsmMakeCall()
|
||
//
|
||
DereferenceCall( pCall );
|
||
|
||
break;
|
||
}
|
||
|
||
default:
|
||
|
||
break;
|
||
|
||
|
||
}
|
||
|
||
TRACE( TL_N, TM_Mp, ("-ExecAdapterWorkItem") );
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
TpReceiveCall(
|
||
IN ADAPTER* pAdapter,
|
||
IN BINDING* pBinding,
|
||
IN PPPOE_PACKET* pPacket
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will be called by miniport when we receive a PADR packet
|
||
to initiate a call.
|
||
|
||
Parameters:
|
||
|
||
pAdapter:
|
||
A pointer to our adapter information structure.
|
||
|
||
pPacket:
|
||
A pointer to the received PADI packet.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
HANDLE_TABLE hCallTable = NULL;
|
||
UINT hCallTableSize = 0;
|
||
UINT nIndex = 0;
|
||
LINE* pLine = NULL;
|
||
CALL* pCall = NULL;
|
||
UINT i;
|
||
NDIS_STATUS status;
|
||
|
||
BOOLEAN fCallInsertedToHandleTable = FALSE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpReceiveCall") );
|
||
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
//
|
||
// Traverse the call handle table and find an empty spot
|
||
//
|
||
hCallTableSize = pAdapter->nMaxLines * pAdapter->nCallsPerLine;
|
||
|
||
hCallTable = pAdapter->TapiProv.hCallTable;
|
||
|
||
for ( nIndex = 0; nIndex < hCallTableSize; nIndex++ )
|
||
{
|
||
|
||
if ( RetrieveFromHandleTableByIndex( hCallTable, (USHORT) nIndex ) == NULL )
|
||
break;
|
||
|
||
}
|
||
|
||
if ( nIndex == hCallTableSize )
|
||
{
|
||
//
|
||
// We are already maxed out with current calls, do not respond to the request
|
||
//
|
||
// TODO: We could send a PADO packet with an error tag saying that we can
|
||
// not accept calls temporarily.
|
||
//
|
||
TRACE( TL_N, TM_Tp, ("-TpReceiveCall: Can not take calls - Call table full") );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
return;
|
||
}
|
||
|
||
//
|
||
// We have found an empty spot, now see if any of the open lines accept calls
|
||
//
|
||
for ( i = 0; i < pAdapter->nMaxLines; i++ )
|
||
{
|
||
pLine = pAdapter->TapiProv.LineTable[i];
|
||
|
||
if ( pLine == NULL )
|
||
continue;
|
||
|
||
if ( pLine->nActiveCalls == pAdapter->nCallsPerLine )
|
||
{
|
||
pLine = NULL;
|
||
|
||
continue;
|
||
}
|
||
|
||
if ( !( pLine->ulLnFlags & LNBF_AcceptIncomingCalls ) )
|
||
{
|
||
pLine = NULL;
|
||
|
||
continue;
|
||
}
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
if ( pLine == NULL )
|
||
{
|
||
//
|
||
// We do not have any lines accepting calls right now
|
||
//
|
||
// TODO: We could send a PADO packet with an error tag saying that there are
|
||
// no active lines accepting calls at the moment.
|
||
//
|
||
TRACE( TL_N, TM_Tp, ("-TpReceiveCall: Can not take calls - No lines taking calls") );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// We have found a line accepting calls, and we have a free spot in call handle table,
|
||
// so create a call context, add it to TapiProv structures, and notify TAPI of the new
|
||
// call
|
||
//
|
||
|
||
do
|
||
{
|
||
HDRV_CALL hdCall;
|
||
|
||
//
|
||
// Create a call context
|
||
//
|
||
if ( ALLOC_CALL( &pCall ) != NDIS_STATUS_SUCCESS )
|
||
{
|
||
status = NDIS_STATUS_RESOURCES;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Initialize the call context
|
||
//
|
||
status = TpCallInitialize( pCall, pLine, (HTAPI_CALL) 0, TRUE /* fIncoming */ );
|
||
|
||
if ( status != NDIS_STATUS_SUCCESS )
|
||
break;
|
||
|
||
//
|
||
// Insert the call context into the tapi provider's handle table
|
||
//
|
||
|
||
hdCall = (HDRV_CALL) InsertToHandleTable( pAdapter->TapiProv.hCallTable,
|
||
(USHORT) nIndex,
|
||
(PVOID) pCall );
|
||
|
||
|
||
if ( hdCall == (HDRV_CALL) NULL )
|
||
{
|
||
status = NDIS_STATUS_TAPI_CALLUNAVAIL;
|
||
|
||
break;
|
||
}
|
||
|
||
fCallInsertedToHandleTable = TRUE;
|
||
|
||
//
|
||
// Set the call's hdCall member
|
||
//
|
||
pCall->hdCall = hdCall;
|
||
|
||
//
|
||
// Insert the call context into the line's active call list
|
||
//
|
||
NdisAcquireSpinLock( &pLine->lockLine );
|
||
|
||
InsertHeadList( &pLine->linkCalls, &pCall->linkCalls );
|
||
|
||
pLine->nActiveCalls++;
|
||
|
||
ReferenceLine( pLine, FALSE );
|
||
|
||
NdisReleaseSpinLock( &pLine->lockLine );
|
||
|
||
//
|
||
// Reference the call 3 times:
|
||
// 1. For running FsmReceiveCall() below
|
||
// 2. For dropping of the call
|
||
// 3. For closing of the call
|
||
//
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
ReferenceCall( pCall, FALSE );
|
||
ReferenceCall( pCall, FALSE );
|
||
ReferenceCall( pCall, FALSE );
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
status = NDIS_STATUS_SUCCESS;
|
||
|
||
} while ( FALSE );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
|
||
//
|
||
// Check the status
|
||
//
|
||
if ( status == NDIS_STATUS_SUCCESS )
|
||
{
|
||
|
||
//
|
||
// Kick the state machine to start receiving the call
|
||
//
|
||
FsmReceiveCall( pCall, pBinding, pPacket );
|
||
|
||
//
|
||
// Remove the reference added above
|
||
//
|
||
DereferenceCall( pCall );
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// If something failed, do clean up
|
||
//
|
||
|
||
if ( fCallInsertedToHandleTable )
|
||
{
|
||
NdisAcquireSpinLock( &pAdapter->lockAdapter );
|
||
|
||
RemoveFromHandleTable( pAdapter->TapiProv.hCallTable, (NDIS_HANDLE) pCall->hdCall );
|
||
|
||
NdisReleaseSpinLock( &pAdapter->lockAdapter );
|
||
}
|
||
|
||
if ( pCall )
|
||
{
|
||
TpCallCleanup( pCall );
|
||
}
|
||
|
||
}
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpReceiveCall=$%x",status) );
|
||
}
|
||
|
||
BOOLEAN
|
||
TpIndicateNewCall(
|
||
IN CALL* pCall
|
||
)
|
||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Functional Description:
|
||
|
||
This function will be called to indicate the new call context to to TAPI.
|
||
|
||
If TAPI can be notified succesfully, then it returns TRUE, otherwise it
|
||
returns FALSE.
|
||
|
||
Parameters:
|
||
|
||
pCall _ New call context to be indicated to TAPI.
|
||
|
||
Return Values:
|
||
|
||
TRUE
|
||
FALSE
|
||
|
||
---------------------------------------------------------------------------*/
|
||
{
|
||
NDIS_TAPI_EVENT TapiEvent;
|
||
BOOLEAN fRet = FALSE;
|
||
|
||
TRACE( TL_N, TM_Tp, ("+TpIndicateNewCall") );
|
||
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
if ( pCall->ulClFlags & CLBF_CallDropped ||
|
||
pCall->ulClFlags & CLBF_CallClosePending )
|
||
{
|
||
TRACE( TL_N, TM_Tp, ("TpIndicateNewCall: Can not indicate new call since call is going down") );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpIndicateNewCall") );
|
||
|
||
//
|
||
// This may happen if call is closed internally due to the FSM timeout handlers
|
||
//
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
return fRet;
|
||
}
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
//
|
||
// Indicate the new call to TAPI, retrieve the corresponding TAPI handle (htCall)
|
||
// and set it in the call
|
||
//
|
||
// Future: The casts below between ulParam2. pCall->hdCall and pCall->htCall will
|
||
// be a problem on 64 bit machines.
|
||
//
|
||
TapiEvent.htLine = pCall->pLine->htLine;
|
||
TapiEvent.htCall = 0;
|
||
TapiEvent.ulMsg = LINE_NEWCALL;
|
||
|
||
TapiEvent.ulParam1 = (ULONG) pCall->hdCall;
|
||
TapiEvent.ulParam2 = 0;
|
||
TapiEvent.ulParam3 = 0;
|
||
|
||
TRACE( TL_N, TM_Tp, ("TpIndicateNewCall: Indicate LINE_NEWCALL") );
|
||
|
||
NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_TAPI_INDICATION,
|
||
&TapiEvent,
|
||
sizeof( NDIS_TAPI_EVENT ) );
|
||
|
||
NdisAcquireSpinLock( &pCall->lockCall );
|
||
|
||
pCall->htCall = (HTAPI_CALL) TapiEvent.ulParam2;
|
||
|
||
fRet = TRUE;
|
||
|
||
NdisReleaseSpinLock( &pCall->lockCall );
|
||
|
||
TRACE( TL_N, TM_Tp, ("-TpIndicateNewCall") );
|
||
|
||
return fRet;
|
||
|
||
}
|