mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4928 lines
137 KiB
4928 lines
137 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Module Name:
|
|
|
|
tapi.c
|
|
|
|
Abstract:
|
|
|
|
This module contains all the TAPI_OID processing routines.
|
|
|
|
Author:
|
|
|
|
Hakan Berk - Microsoft, Inc. ([email protected]) 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’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;
|
|
|
|
}
|