Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

865 lines
25 KiB

/*
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
(C) Copyright 1999
All rights reserved.
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
Portions of this software are:
(C) Copyright 1995 TriplePoint, Inc. -- http://www.TriplePoint.com
License to use this software is granted under the same terms
outlined in the Microsoft Windows Device Driver Development Kit.
(C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
License to use this software is granted under the terms outlined in
the Microsoft Windows Device Driver Development Kit.
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@doc INTERNAL DChannel DChannel_c
@module DChannel.c |
This module implements the interface to the <t DCHANNEL_OBJECT>.
Supports the high-level channel control functions used by the CONDIS WAN
Minport driver.
@comm
This module isolates most the vendor specific Call Control interfaces.
It will require some changes to accomodate your hardware device's call
control mechanism.
@head3 Contents |
@index class,mfunc,func,msg,mdata,struct,enum | DChannel_c
@end
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
*/
#define __FILEID__ DCHANNEL_OBJECT_TYPE
// Unique file ID for error logging
#include "Miniport.h" // Defines all the miniport objects
#if defined(NDIS_LCODE)
# pragma NDIS_LCODE // Windows 9x wants this code locked down!
# pragma NDIS_LDATA
#endif
DBG_STATIC ULONG g_DChannelInstanceCounter // @globalv
// Keeps track of how many <t DCHANNEL_OBJECT>s are created.
= 0;
/* @doc EXTERNAL INTERNAL DChannel DChannel_c g_DChannelParameters
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@topic 5.4 DChannel Parameters |
This section describes the registry parameters read into the
<t DCHANNEL_OBJECT>.
@globalv PARAM_TABLE | g_DChannelParameters |
This table defines the registry based parameters to be assigned to data
members of the <t DCHANNEL_OBJECT>.
<f Note>:
If you add any registry based data members to <t DCHANNEL_OBJECT>
you will need to modify <f DChannelReadParameters> and add the parameter
definitions to the <f g_DChannelParameters> table.
*/
DBG_STATIC PARAM_TABLE g_DChannelParameters[] =
{
PARAM_ENTRY(DCHANNEL_OBJECT,
TODO, PARAM_TODO,
FALSE, NdisParameterInteger, 0,
0, 0, 0),
/* The last entry must be an empty string! */
{ { 0 } }
};
/* @doc INTERNAL DChannel DChannel_c DChannelReadParameters
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelReadParameters> reads the DChannel parameters from the registry
and initializes the associated data members. This should only be called
by <f DChannelCreate>.
<f Note>:
If you add any registry based data members to <t DCHANNEL_OBJECT>
you will need to modify <f DChannelReadParameters> and add the parameter
definitions to the <f g_DChannelParameters> table.
@rdesc
<f DChannelReadParameters> returns zero if it is successful.<nl>
Otherwise, a non-zero return value indicates an error condition.
*/
DBG_STATIC NDIS_STATUS DChannelReadParameters(
IN PDCHANNEL_OBJECT pDChannel // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
)
{
DBG_FUNC("DChannelReadParameters")
NDIS_STATUS Status;
// Status result returned from an NDIS function call.
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
/*
// Parse the registry parameters.
*/
Status = ParamParseRegistry(
pAdapter->MiniportAdapterHandle,
pAdapter->WrapperConfigurationContext,
(PUCHAR)pDChannel,
g_DChannelParameters
);
if (Status == NDIS_STATUS_SUCCESS)
{
/*
// Make sure the parameters are valid.
*/
if (pDChannel->TODO)
{
DBG_ERROR(pAdapter,("Invalid parameter\n"
));
NdisWriteErrorLogEntry(
pAdapter->MiniportAdapterHandle,
NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
3,
pDChannel->TODO,
__FILEID__,
__LINE__
);
Status = NDIS_STATUS_FAILURE;
}
else
{
/*
// Finish setting up data members based on registry settings.
*/
}
}
DBG_RETURN(pAdapter, Status);
return (Status);
}
/* @doc INTERNAL DChannel DChannel_c DChannelCreateObjects
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelCreateObjects> calls the create routines for all the objects
contained in <t DCHANNEL_OBJECT>. This should only be called
by <f DChannelCreate>.
<f Note>:
If you add any new objects to <t DCHANNEL_OBJECT> you will need
to modify <f DChannelCreateObjects> and <f DChannelDestroyObjects> so they
will get created and destroyed properly.
@rdesc
<f DChannelCreateObjects> returns zero if it is successful.<nl>
Otherwise, a non-zero return value indicates an error condition.
*/
DBG_STATIC NDIS_STATUS DChannelCreateObjects(
IN PDCHANNEL_OBJECT pDChannel // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
)
{
DBG_FUNC("DChannelCreateObjects")
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
// Holds the result code returned by this function.
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
// TODO - Add code here to allocate any sub-objects needed to support
// your physical DChannels.
DBG_RETURN(pAdapter, Result);
return (Result);
}
/* @doc INTERNAL DChannel DChannel_c DChannelCreate
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelCreate> allocates memory for a <t DCHANNEL_OBJECT> and then
initializes the data members to their starting state.
If successful, <p ppDChannel> will be set to point to the newly created
<t DCHANNEL_OBJECT>. Otherwise, <p ppDChannel> will be set to NULL.
@comm
This function should be called only once when the Miniport is loaded.
Before the Miniport is unloaded, <f DChannelDestroy> must be called to
release the <t DCHANNEL_OBJECT> created by this function.
@rdesc
<f DChannelCreate> returns zero if it is successful.<nl>
Otherwise, a non-zero return value indicates an error condition.
*/
NDIS_STATUS DChannelCreate(
OUT PDCHANNEL_OBJECT * ppDChannel, // @parm
// Points to a caller-defined memory location to which this function
// writes the virtual address of the allocated <t DCHANNEL_OBJECT>.
IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
)
{
DBG_FUNC("DChannelCreate")
PDCHANNEL_OBJECT pDChannel;
// Pointer to our newly allocated object.
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
// Holds the result code returned by this function.
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
DBG_ENTER(pAdapter);
/*
// Make sure the caller's object pointer is NULL to begin with.
// It will be set later only if everything is successful.
*/
*ppDChannel = NULL;
/*
// Allocate memory for the object.
*/
Result = ALLOCATE_OBJECT(pDChannel, pAdapter->MiniportAdapterHandle);
if (Result == NDIS_STATUS_SUCCESS)
{
/*
// Zero everything to begin with.
// Then set the object type and assign a unique ID .
*/
pDChannel->ObjectType = DCHANNEL_OBJECT_TYPE;
pDChannel->ObjectID = ++g_DChannelInstanceCounter;
/*
// Initialize the member variables to their default settings.
*/
pDChannel->pAdapter = pAdapter;
// TODO - Add code here to allocate any resources needed to support
// your physical DChannels.
/*
// Parse the registry parameters.
*/
Result = DChannelReadParameters(pDChannel);
/*
// If all goes well, we are ready to create the sub-components.
*/
if (Result == NDIS_STATUS_SUCCESS)
{
Result = DChannelCreateObjects(pDChannel);
}
if (Result == NDIS_STATUS_SUCCESS)
{
/*
// All is well, so return the object pointer to the caller.
*/
*ppDChannel = pDChannel;
}
else
{
/*
// Something went wrong, so let's make sure everything is
// cleaned up.
*/
DChannelDestroy(pDChannel);
}
}
DBG_RETURN(pAdapter, Result);
return (Result);
}
/* @doc INTERNAL DChannel DChannel_c DChannelDestroyObjects
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelDestroyObjects> calls the destroy routines for all the objects
contained in <t DCHANNEL_OBJECT>. This should only be called by
<f DChannelDestroy>.
<f Note>: If you add any new objects to <t PDCHANNEL_OBJECT> you will need to
modify <f DChannelCreateObjects> and <f DChannelDestroyObjects> so they
will get created and destroyed properly.
*/
DBG_STATIC void DChannelDestroyObjects(
IN PDCHANNEL_OBJECT pDChannel // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
)
{
DBG_FUNC("DChannelDestroyObjects")
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
// TODO - Add code here to release any sub-objects allocated by
// DChannelCreateObjects.
DBG_LEAVE(pAdapter);
}
/* @doc INTERNAL DChannel DChannel_c DChannelDestroy
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelDestroy> frees the memory for this <t DCHANNEL_OBJECT>.
All memory allocated by <f DChannelCreate> will be released back to the
OS.
*/
void DChannelDestroy(
IN PDCHANNEL_OBJECT pDChannel // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
)
{
DBG_FUNC("DChannelDestroy")
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
if (pDChannel)
{
ASSERT(pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
// TODO - Add code here to release any resources allocated by
// DChannelCreate.
/*
// Release all objects allocated within this object.
*/
DChannelDestroyObjects(pDChannel);
/*
// Make sure we fail the ASSERT if we see this object again.
*/
pDChannel->ObjectType = 0;
FREE_OBJECT(pDChannel);
DBG_LEAVE(pAdapter);
}
}
/* @doc INTERNAL DChannel DChannel_c DChannelInitialize
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelInitialize> resets all the internal data members contained
in <t BCHANNEL_OBJECT> back to their initial state.
<f Note>:
If you add any new members to <t DCHANNEL_OBJECT> you will need to
modify <f DChannelInitialize> to initialize your new data mamebers.
*/
void DChannelInitialize(
IN PDCHANNEL_OBJECT pDChannel // @parm
// A pointer to the <t BCHANNEL_OBJECT> returned by <f DChannelCreate>.
)
{
DBG_FUNC("DChannelInitialize")
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
// TODO - Add code here to initialize all the physical D-Channels on
// your adapter.
DBG_LEAVE(pAdapter);
}
/* @doc INTERNAL DChannel DChannel_c DChannelOpen
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelOpen> establishes a communications path between the miniport
and the DChannel.
@rdesc
<f DChannelOpen> returns zero if it is successful.<nl>
Otherwise, a non-zero return value indicates an error condition.
*/
NDIS_STATUS DChannelOpen(
IN PDCHANNEL_OBJECT pDChannel // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
)
{
DBG_FUNC("DChannelOpen")
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
// Holds the result code returned by this function.
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
if (++pDChannel->IsOpen == 1)
{
DBG_NOTICE(pAdapter,("Opening DChannel #%d\n",
pDChannel->ObjectID));
// TODO - Add code here to open all the physical D-Channels on
// your adapter.
}
else
{
DBG_NOTICE(pAdapter,("DChannel #%d already opened\n",
pDChannel->ObjectID));
}
DBG_RETURN(pAdapter, Result);
return (Result);
}
/* @doc INTERNAL DChannel DChannel_c DChannelClose
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelClose> tears down the communications path between the miniport
and the DChannel.
*/
void DChannelClose(
IN PDCHANNEL_OBJECT pDChannel // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
)
{
DBG_FUNC("DChannelClose")
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
if (pDChannel->IsOpen == 1)
{
DBG_NOTICE(pAdapter,("Closing DChannel #%d\n",
pDChannel->ObjectID));
// TODO - Add code here to close all the physical D-Channels on
// your adapter.
pDChannel->IsOpen = 0;
}
else if (pDChannel->IsOpen == 0)
{
DBG_WARNING(pAdapter,("DChannel #%d already closed\n",
pDChannel->ObjectID));
}
else
{
pDChannel->IsOpen--;
}
DBG_LEAVE(pAdapter);
}
/* @doc INTERNAL DChannel DChannel_c DChannelMakeCall
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelMakeCall> places a call over the selected line device.
@rdesc
<f DChannelMakeCall> returns zero if it is successful.<nl>
Otherwise, a non-zero return value indicates an error condition.
*/
NDIS_STATUS DChannelMakeCall(
IN PDCHANNEL_OBJECT pDChannel, // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
IN PBCHANNEL_OBJECT pBChannel, // @parm
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
IN PUCHAR DialString, // @parm
// A pointer to an ASCII null-terminated string of digits.
IN USHORT DialStringLength, // @parm
// Number of bytes in dial string.
IN PLINE_CALL_PARAMS pLineCallParams // @parm
// A pointer to the TAPI <t LINE_CALL_PARAMS> to be used for this call.
)
{
DBG_FUNC("DChannelMakeCall")
NDIS_STATUS Result = NDIS_STATUS_RESOURCES;
// Holds the result code returned by this function.
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
ASSERT(pDChannel->IsOpen);
pDChannel->TotalMakeCalls++;
pBChannel->Flags |= VCF_OUTGOING_CALL;
pBChannel->CallState = LINECALLSTATE_DIALING;
#if defined(SAMPLE_DRIVER)
// This sample code uses the phone number to select one of the other
// BChannels on which to complete the connection.
{
PBCHANNEL_OBJECT pPeerBChannel;
PCARD_EVENT_OBJECT pEvent;
pPeerBChannel = GET_BCHANNEL_FROM_PHONE_NUMBER(DialString);
if (pPeerBChannel)
{
pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
if (pEvent)
{
pEvent->ulEventCode = CARD_EVENT_RING;
pEvent->pSendingObject = pBChannel;
pEvent->pReceivingObject = pPeerBChannel;
pBChannel->pPeerBChannel = pPeerBChannel;
CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
Result = NDIS_STATUS_PENDING;
}
}
else
{
DBG_ERROR(pAdapter,("Cannot map phone number '%s' to BChannel\n",
DialString));
}
}
#else // SAMPLE_DRIVER
// TODO - Add code here to place a call.
#endif // SAMPLE_DRIVER
DBG_RETURN(pAdapter, Result);
return (Result);
}
/* @doc INTERNAL DChannel DChannel_c DChannelAnswerCall
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelAnswerCall> answers the incoming call so it can be connected.
@rdesc
<f DChannelAnswerCall> returns zero if it is successful.<nl>
Otherwise, a non-zero return value indicates an error condition.
*/
NDIS_STATUS DChannelAnswerCall(
IN PDCHANNEL_OBJECT pDChannel, // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
IN PBCHANNEL_OBJECT pBChannel // @parm
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
)
{
DBG_FUNC("DChannelAnswerCall")
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
// Holds the result code returned by this function.
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
ASSERT(pDChannel->IsOpen);
pDChannel->TotalAnswers++;
#if defined(SAMPLE_DRIVER)
// This sample code sends a connect over to the calling BChannel.
{
PCARD_EVENT_OBJECT pEvent;
PBCHANNEL_OBJECT pPeerBChannel = pBChannel->pPeerBChannel;
if (pPeerBChannel)
{
pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
if (pEvent)
{
pEvent->ulEventCode = CARD_EVENT_CONNECT;
pEvent->pSendingObject = pBChannel;
pEvent->pReceivingObject = pPeerBChannel;
CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
}
else
{
Result = NDIS_STATUS_RESOURCES;
}
}
else
{
DBG_ERROR(pAdapter,("pPeerBChannel == NULL\n"));
Result = NDIS_STATUS_RESOURCES;
}
}
#else // SAMPLE_DRIVER
// TODO - Add code here to answer a call.
// If you return NDIS_STATUS_PENDING from here, you must perform the
// following actions when the call is finally answered.
// pBChannel->CallState = LINECALLSTATE_CONNECTED;
// NdisMCmDispatchCallConnected(pBChannel->NdisVcHandle);
// If you fail to answer for some reason you must call:
// InitiateCallTeardown(pAdapter, pBChannel);
#endif // SAMPLE_DRIVER
DBG_RETURN(pAdapter, Result);
return (Result);
}
/* @doc INTERNAL DChannel DChannel_c DChannelCloseCall
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelCloseCall> closes a previously opened call instance as
initiated from <f DChannelMakeCall> or <f DChannelAnswerCall>. After
the call is closed, no one else should reference it.
@rdesc
<f DChannelCloseCall> returns zero if it is successful.<nl>
Otherwise, a non-zero return value indicates an error condition.
*/
NDIS_STATUS DChannelCloseCall(
IN PDCHANNEL_OBJECT pDChannel, // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
IN PBCHANNEL_OBJECT pBChannel // @parm
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
)
{
DBG_FUNC("DChannelCloseCall")
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
// Holds the result code returned by this function.
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
ASSERT(pDChannel->IsOpen);
// This routine may be called several times during line/call cleanup.
// If the call is already closed, just return success.
if (pBChannel->CallState != 0 &&
pBChannel->CallState != LINECALLSTATE_IDLE)
{
#if defined(SAMPLE_DRIVER)
// This sample code sends a disconnect over to the connected BChannel.
PCARD_EVENT_OBJECT pEvent;
PBCHANNEL_OBJECT pPeerBChannel = pBChannel->pPeerBChannel;
if (pPeerBChannel)
{
pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
if (pEvent)
{
// Indicate call disconnect to the other channel.
pEvent->ulEventCode = CARD_EVENT_DISCONNECT;
pEvent->pSendingObject = pBChannel;
pEvent->pReceivingObject = pPeerBChannel;
CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
}
pBChannel->pPeerBChannel = NULL;
}
else
{
DBG_WARNING(pAdapter,("#%d NO PEER CHANNEL - CALLSTATE=%X\n",
pBChannel->ObjectID, pBChannel->CallState));
}
// Return any pending packets to the protocol stack.
pBChannel->CallState = LINECALLSTATE_IDLE;
#else // SAMPLE_DRIVER
// TODO - Add code here to drop a call.
#endif // SAMPLE_DRIVER
// Make sure there are no packets left on this channel before it closes.
FlushSendPackets(pAdapter, pBChannel);
}
else
{
DBG_NOTICE(pAdapter,("#%d ALREADY IDLE - CALLSTATE=%X\n",
pBChannel->ObjectID, pBChannel->CallState));
}
DBG_RETURN(pAdapter, Result);
return (Result);
}
/* @doc INTERNAL DChannel DChannel_c DChannelRejectCall
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
@func
<f DChannelRejectCall> rejects an incoming call on the specified
channel.
*/
VOID DChannelRejectCall(
IN PDCHANNEL_OBJECT pDChannel, // @parm
// A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
IN PBCHANNEL_OBJECT pBChannel // @parm
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
)
{
DBG_FUNC("DChannelRejectCall")
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
DBG_ENTER(pAdapter);
if (pBChannel->CallState != 0 &&
pBChannel->CallState != LINECALLSTATE_IDLE)
{
#if defined(SAMPLE_DRIVER)
// This sample code sends a disconnect over to the connected BChannel.
PCARD_EVENT_OBJECT pEvent;
PBCHANNEL_OBJECT pPeerBChannel = pBChannel->pPeerBChannel;
if (pPeerBChannel)
{
pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
if (pEvent)
{
// Indicate call disconnect to the other channel.
pEvent->ulEventCode = CARD_EVENT_DISCONNECT;
pEvent->pSendingObject = pBChannel;
pEvent->pReceivingObject = pPeerBChannel;
CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
}
pBChannel->pPeerBChannel = NULL;
}
else
{
DBG_WARNING(pAdapter,("#%d NO PEER CHANNEL - CALLSTATE=%X\n",
pBChannel->ObjectID, pBChannel->CallState));
}
// Return any pending packets to the protocol stack.
pBChannel->CallState = LINECALLSTATE_IDLE;
#else // SAMPLE_DRIVER
// TODO - Add code here to reject an incoming call.
#endif // SAMPLE_DRIVER
}
DBG_LEAVE(pAdapter);
}