1841 lines
52 KiB
C
1841 lines
52 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
callmgr.c
|
|
|
|
Abstract:
|
|
|
|
Call manager peice of the irda NDIS 5 miniport (WAN driver)
|
|
|
|
Author:
|
|
|
|
mbert 9-97
|
|
|
|
|
|
RasIrda is a connection oriented Ndis 5 miniport with an integrated call manager.
|
|
Proxy is the Ndis Tapi proxy (ndproxy.sys) and is the only client protocol that
|
|
makes calls over RasIrda.
|
|
Irda is a TDI transport driver (irda.sys). RasIrda uses irtdicl.lib to
|
|
interface with irda.sys in order to abstract the complexity of the TDI client
|
|
interface.
|
|
|
|
*******************
|
|
Standard Call Setup
|
|
*******************
|
|
|
|
Client Server
|
|
|
|
Proxy RasIrda Irda RasIrda Proxy
|
|
_______________________________________________________________________________
|
|
|
|
RasIrCmCreateVc
|
|
---------------->
|
|
|
|
RasIrCmMakeCall
|
|
---------------->
|
|
|
|
IrdaDiscoverDevices
|
|
IrdaOpenConnection
|
|
-------------------->
|
|
|
|
IrdaIncomingConnection
|
|
------------------>
|
|
pVc->Flags =
|
|
IRDA_OPEN
|
|
|
|
NdisMCmCallComplete +RasIrCmCreateVc
|
|
<----------------- pvc->Flags =
|
|
CREATED_LOCAL
|
|
pVc->Flags = IRDA_OPEN
|
|
IRDA_OPEN
|
|
VC_OPEN NdisMCmActivateVc
|
|
------------------>
|
|
|
|
|
|
NdisMCmDispatchIncomingCall
|
|
------------------>
|
|
|
|
RasIrCmIncomingCallComplete
|
|
<----------------
|
|
|
|
pVc->Flags =
|
|
CREATED_LOCAL
|
|
IRDA_OPEN
|
|
VC_OPEN
|
|
|
|
===============================================================================
|
|
|
|
*****************
|
|
Client Disconnect
|
|
*****************
|
|
|
|
Client Server
|
|
|
|
Proxy RasIrda Irda RasIrda Proxy
|
|
_______________________________________________________________________________
|
|
|
|
pVc->Flags = pVc->Flags =
|
|
IRDA_OPEN CREATED_LOCAL
|
|
VC_OPEN IRDA_OPEN
|
|
VC_OPEN
|
|
|
|
RasIrCmCloseCall
|
|
--------------->
|
|
|
|
IrdaCloseConnection
|
|
------------------->
|
|
pVc->Flags =
|
|
VC_OPEN
|
|
|
|
IrdaConnectionClose
|
|
----------------->
|
|
pVc->Flags =
|
|
CREATED_LOCAL
|
|
VC_OPEN
|
|
|
|
|
|
NdisMCmCloseCallComplete
|
|
<------------------
|
|
IrdaCloseConnection
|
|
<------------
|
|
RasIrCmDeleteVc
|
|
----------------> NdisMCmDispatchIncomingCloseCall
|
|
----------------->
|
|
|
|
RasIrCmCloseCall
|
|
<---------------
|
|
|
|
NdisMCmCloseCallComplete
|
|
------------------>
|
|
|
|
+RasIrCmDeleteVc
|
|
|
|
===============================================================================
|
|
|
|
*****************
|
|
Server Disconnect
|
|
*****************
|
|
|
|
Client Server
|
|
|
|
Proxy RasIrda Irda RasIrda Proxy
|
|
_______________________________________________________________________________
|
|
|
|
pVc->Flags = pVc->Flags =
|
|
IRDA_OPEN CREATED_LOCAL
|
|
VC_OPEN IRDA_OPEN
|
|
VC_OPEN
|
|
|
|
RasIrCmCloseCall
|
|
<---------------
|
|
|
|
IrdaCloseConnection
|
|
<------------
|
|
pVc->Flags =
|
|
CREATED_LOCAL
|
|
VC_OPEN
|
|
|
|
|
|
IrdaConnectionClose NdisMCmCloseCallComplete
|
|
<----------------- ------------------>
|
|
pVc->Flags =
|
|
VC_OPEN +RasIrCmDeleteVc
|
|
|
|
IrdaCloseConnection
|
|
--------------->
|
|
|
|
NdisMCmDispathIncomingCloseConn
|
|
<---------------------
|
|
|
|
RasIrCmCloseCall
|
|
--------------->
|
|
|
|
NdisMCmCloseCallComplete
|
|
<----------------------
|
|
|
|
RasIrCmDeleteVc
|
|
--------------->
|
|
|
|
===============================================================================
|
|
|
|
--*/
|
|
|
|
#include "rasirdap.h"
|
|
|
|
NDIS_STATUS
|
|
RasIrCmCreateVc(
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE NdisVcHandle,
|
|
OUT PNDIS_HANDLE ProtocolVcContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = ProtocolAfContext;
|
|
PRASIR_VC pVc;
|
|
NDIS_STATUS Status;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
NdisAllocateMemoryWithTag((PVOID *)&pVc, sizeof(RASIR_VC), MT_RASIR_VC);
|
|
|
|
if (pVc == NULL)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: RasIrCmCreateVc failed, resources\n"));
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
NdisZeroMemory(pVc, sizeof(*pVc));
|
|
|
|
#if DBG
|
|
pVc->Sig = (ULONG) VC_SIG;
|
|
#endif
|
|
|
|
pVc->pAdapter = pAdapter;
|
|
pVc->NdisVcHandle = NdisVcHandle;
|
|
|
|
pVc->LinkInfo.MaxSendFrameSize = pAdapter->Info.MaxFrameSize;
|
|
pVc->LinkInfo.MaxRecvFrameSize = pAdapter->Info.MaxFrameSize;
|
|
pVc->LinkInfo.SendFramingBits = pAdapter->Info.FramingBits;
|
|
pVc->LinkInfo.RecvFramingBits = pAdapter->Info.FramingBits;
|
|
pVc->LinkInfo.SendACCM = (ULONG) -1;
|
|
pVc->LinkInfo.RecvACCM = (ULONG) -1;
|
|
|
|
InitializeListHead(&pVc->CompletedAsyncBufList);
|
|
|
|
ReferenceInit(&pVc->RefCnt, pVc, DeleteVc);
|
|
|
|
REFADD(&pVc->RefCnt, ' TS1');
|
|
|
|
NdisInterlockedInsertTailList(&pAdapter->VcList,
|
|
&pVc->Linkage,
|
|
&pAdapter->SpinLock);
|
|
|
|
NdisAllocatePacketPool(&Status,
|
|
&pVc->RxPacketPool,
|
|
IRTDI_RECV_BUF_CNT * 2, 0);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisAllocatePacketPool failed %X\n",
|
|
Status));
|
|
goto done;
|
|
}
|
|
|
|
NdisAllocateBufferPool(&Status,
|
|
&pVc->RxBufferPool,
|
|
IRTDI_RECV_BUF_CNT);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisAllocateBufferPool failed %X\n",
|
|
Status));
|
|
goto done;
|
|
}
|
|
|
|
*ProtocolVcContext = pVc;
|
|
|
|
done:
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmCreateVc status %X, vc:%X\n",
|
|
Status, pVc));
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
REFDEL(&pVc->RefCnt, ' TS1');
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmDeleteVc(
|
|
IN NDIS_HANDLE ProtocolVcContext)
|
|
{
|
|
PRASIR_VC pVc = ProtocolVcContext;
|
|
PASYNC_BUFFER pAsyncBuf;
|
|
|
|
GOODVC(pVc);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmDeleteVc vc:%X\n", pVc));
|
|
|
|
if (pVc->pCurrAsyncBuf)
|
|
{
|
|
NdisFreeToNPagedLookasideList(&pVc->pAdapter->AsyncBufLList,
|
|
pVc->pCurrAsyncBuf);
|
|
}
|
|
|
|
while ((pAsyncBuf = (PASYNC_BUFFER) NdisInterlockedRemoveHeadList(
|
|
&pVc->CompletedAsyncBufList,
|
|
&pVc->pAdapter->SpinLock)) != NULL)
|
|
{
|
|
NdisFreeToNPagedLookasideList(&pVc->pAdapter->AsyncBufLList,
|
|
pAsyncBuf);
|
|
}
|
|
|
|
REFDEL(&pVc->RefCnt, ' TS1');
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmOpenAf(
|
|
IN NDIS_HANDLE CallMgrBindingContext,
|
|
IN PCO_ADDRESS_FAMILY AddressFamily,
|
|
IN NDIS_HANDLE NdisAfHandle,
|
|
OUT PNDIS_HANDLE CallMgrAfContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = (PRASIR_ADAPTER) CallMgrBindingContext;
|
|
NDIS_HANDLE hExistingAf;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
|
|
if ((AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_TAPI_PROXY)) {
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIRDA: bad address family %08lx\n",AddressFamily->AddressFamily));
|
|
|
|
return NDIS_STATUS_INVALID_ADDRESS;
|
|
}
|
|
|
|
|
|
pAdapter->Flags = 0;
|
|
|
|
hExistingAf = (NDIS_HANDLE)
|
|
InterlockedCompareExchangePointer(
|
|
&pAdapter->NdisAfHandle, NdisAfHandle, NULL );
|
|
|
|
if (hExistingAf)
|
|
{
|
|
// Our AF has already been opened and it doesn't make any sense to
|
|
// accept another since there is no way to distinguish which should
|
|
// receive incoming calls.
|
|
//
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: OpenAddressFamily again!\n"));
|
|
ASSERT( !"AF exists?" );
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
*CallMgrAfContext = CallMgrBindingContext;
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmCloseAf(
|
|
IN NDIS_HANDLE CallMgrAfContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = (PRASIR_ADAPTER) CallMgrAfContext;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
if (pAdapter->NdisSapHandle != NULL)
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmCloseAf pending, Outstanding registered SAP\n"));
|
|
|
|
pAdapter->Flags |= ADF_PENDING_AF_CLOSE;
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmCloseAf\n"));
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
CloseNextAdapterEndpoint(
|
|
PRASIR_ADAPTER pAdapter)
|
|
{
|
|
PRASIR_IRDA_ENDPOINT pEndp;
|
|
|
|
pEndp = (PRASIR_IRDA_ENDPOINT) NdisInterlockedRemoveHeadList(
|
|
&pAdapter->EndpList,
|
|
&pAdapter->SpinLock);
|
|
|
|
//
|
|
// Remove the first endpoint and close it.
|
|
// The remaining endpoints are closed in
|
|
// the completetion of this endpoint close
|
|
// (see IrdaCloseEndpointComplete)
|
|
//
|
|
|
|
if (pEndp != NULL)
|
|
{
|
|
GOODENDP(pEndp);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->IrdaCloseEndpoint endp:%X\n",
|
|
pEndp));
|
|
|
|
IrdaCloseEndpoint(pEndp->IrdaEndpContext);
|
|
|
|
return TRUE; // an endpoint was closed
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
OpenNewIrdaEndpoint(
|
|
PRASIR_ADAPTER pAdapter,
|
|
ULONG EndpointType,
|
|
PCHAR ServiceName,
|
|
ULONG ServiceNameSize)
|
|
{
|
|
PRASIR_IRDA_ENDPOINT pEndp;
|
|
TDI_ADDRESS_IRDA ListenAddr;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
NdisAllocateMemoryWithTag((PVOID *) &pEndp,
|
|
sizeof(RASIR_IRDA_ENDPOINT),
|
|
MT_RASIR_ENDP);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: OpenNewIrdaEndpoint %X type %d on service %s\n",
|
|
pEndp, EndpointType, ServiceName));
|
|
|
|
if (pEndp == NULL)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
goto EXIT;
|
|
}
|
|
|
|
pEndp->pAdapter = pAdapter;
|
|
pEndp->EndpType = EndpointType;
|
|
pEndp->Sig = (ULONG) ENDP_SIG;
|
|
|
|
#if DBG
|
|
RtlCopyMemory(pEndp->ServiceName,
|
|
ServiceName,
|
|
ServiceNameSize);
|
|
#endif
|
|
|
|
RtlCopyMemory(ListenAddr.irdaServiceName,
|
|
ServiceName,
|
|
ServiceNameSize);
|
|
|
|
Status = IrdaOpenEndpoint(pEndp,
|
|
&ListenAddr,
|
|
&pEndp->IrdaEndpContext);
|
|
|
|
EXIT:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: OpenNewIrdaEndpoint failed %X\n",
|
|
Status));
|
|
|
|
if (pEndp)
|
|
{
|
|
NdisFreeMemory(pEndp, 0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NdisInterlockedInsertTailList(
|
|
&pAdapter->EndpList,
|
|
&pEndp->Linkage,
|
|
&pAdapter->SpinLock);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
RegisterSapPassive(
|
|
IN NDIS_WORK_ITEM* pWork,
|
|
IN VOID* pContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = (PRASIR_ADAPTER) pContext;
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE hOldSap;
|
|
PRASIR_IRDA_ENDPOINT pEndp;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RegisterSapPassive\n"));
|
|
|
|
NdisFreeToNPagedLookasideList(&pAdapter->WorkItemsLList, pWork);
|
|
|
|
hOldSap = pAdapter->NdisSapHandle;
|
|
|
|
if (pAdapter->ModemPort == FALSE)
|
|
{
|
|
|
|
Status = OpenNewIrdaEndpoint(pAdapter,
|
|
EPT_DIRECT,
|
|
RASIR_SERVICE_NAME_DIRECT,
|
|
sizeof(RASIR_SERVICE_NAME_DIRECT));
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
goto EXIT;
|
|
}
|
|
|
|
Status = OpenNewIrdaEndpoint(pAdapter,
|
|
EPT_ASYNC,
|
|
RASIR_SERVICE_NAME_ASYNC,
|
|
sizeof(RASIR_SERVICE_NAME_ASYNC));
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Ignoring SAP registration for ModemPort\n"));
|
|
Status = NDIS_STATUS_SUCCESS; // We don't except incoming connections for modems
|
|
}
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
CloseNextAdapterEndpoint(pAdapter);
|
|
goto EXIT;
|
|
}
|
|
|
|
EXIT:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
pAdapter->NdisSapHandle = NULL;
|
|
}
|
|
|
|
NdisMCmRegisterSapComplete(Status, hOldSap, (NDIS_HANDLE) pAdapter);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmRegisterSapComplete status %X\n",
|
|
Status));
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmRegisterSap(
|
|
IN NDIS_HANDLE CallMgrAfContext,
|
|
IN PCO_SAP Sap,
|
|
IN NDIS_HANDLE NdisSapHandle,
|
|
OUT PNDIS_HANDLE CallMgrSapContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = (PRASIR_ADAPTER) CallMgrAfContext;
|
|
NDIS_HANDLE hExistingSap;
|
|
NDIS_STATUS Status;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmRegisterSap\n"));
|
|
|
|
hExistingSap = (NDIS_HANDLE)
|
|
InterlockedCompareExchangePointer(
|
|
&pAdapter->NdisSapHandle, NdisSapHandle, NULL);
|
|
|
|
if (hExistingSap)
|
|
{
|
|
// A SAP has already been registered and it doesn't make any sense to
|
|
// accept another since there are no SAP parameters to distinguish
|
|
// them.
|
|
//
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Registering SAP again, why. WHY??\n"));
|
|
return NDIS_STATUS_SAP_IN_USE;
|
|
}
|
|
|
|
*CallMgrSapContext = (NDIS_HANDLE )pAdapter;
|
|
|
|
Status = ScheduleWork(pAdapter, RegisterSapPassive, pAdapter);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
InterlockedExchangePointer(&pAdapter->NdisSapHandle, NULL);
|
|
return Status;
|
|
}
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
VOID
|
|
CompleteSapDeregistration(
|
|
PRASIR_ADAPTER pAdapter)
|
|
{
|
|
NDIS_HANDLE hOldSap;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
if ((pAdapter->Flags & ADF_SAP_DEREGISTERED) == 0)
|
|
{
|
|
//
|
|
// Sap deregisteration never occured
|
|
// (failure path for RegisterSap)
|
|
//
|
|
return;
|
|
}
|
|
|
|
hOldSap=InterlockedExchangePointer(&pAdapter->NdisSapHandle, NULL);
|
|
|
|
if (hOldSap)
|
|
{
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmDeregisterSapComp\n"));
|
|
|
|
NdisMCmDeregisterSapComplete(NDIS_STATUS_SUCCESS, hOldSap);
|
|
}
|
|
|
|
if (pAdapter->Flags & ADF_PENDING_AF_CLOSE)
|
|
|
|
{
|
|
pAdapter->Flags &= ~ADF_PENDING_AF_CLOSE;
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmCloseAddresFamilyComplete hAf:%X\n",
|
|
pAdapter->NdisAfHandle));
|
|
|
|
NdisMCmCloseAddressFamilyComplete(NDIS_STATUS_SUCCESS,
|
|
pAdapter->NdisAfHandle);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
IrdaCloseEndpointComplete(
|
|
IN PVOID ClEndpContext)
|
|
{
|
|
PRASIR_IRDA_ENDPOINT pEndp = (PRASIR_IRDA_ENDPOINT) ClEndpContext;
|
|
PRASIR_ADAPTER pAdapter;
|
|
|
|
GOODENDP(pEndp);
|
|
|
|
pAdapter = pEndp->pAdapter;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: IrdaCloseEndpointComplete adapter:%X, endp:%X\n",
|
|
pAdapter, pEndp));
|
|
|
|
pEndp->Sig = 0x66666666;
|
|
|
|
NdisFreeMemory(pEndp, 0,0);
|
|
|
|
if (CloseNextAdapterEndpoint(pAdapter) == FALSE)
|
|
{
|
|
CompleteSapDeregistration(pAdapter);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
DeregisterSapPassive(
|
|
IN NDIS_WORK_ITEM* pWork,
|
|
IN VOID* pContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = (PRASIR_ADAPTER) pContext;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: DeregisterSapPassive\n"));
|
|
|
|
NdisFreeToNPagedLookasideList(&pAdapter->WorkItemsLList, pWork);
|
|
|
|
if (CloseNextAdapterEndpoint(pAdapter) == FALSE)
|
|
{
|
|
CompleteSapDeregistration(pAdapter);
|
|
}
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmDeregisterSap(
|
|
NDIS_HANDLE CallMgrSapContext)
|
|
{
|
|
PRASIR_ADAPTER pAdapter = (PRASIR_ADAPTER) CallMgrSapContext;
|
|
NDIS_STATUS Status;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
pAdapter->Flags |= ADF_SAP_DEREGISTERED;
|
|
|
|
Status = ScheduleWork(pAdapter, DeregisterSapPassive, pAdapter);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: RasIrCmDeregisterSap failed\n"));
|
|
return Status;
|
|
}
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: RasIrCmDeregisterSap pending\n"));
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
VOID
|
|
CompleteMakeCall(
|
|
PRASIR_VC pVc,
|
|
NDIS_STATUS Status)
|
|
{
|
|
ULONG ConnectionSpeed;
|
|
|
|
pVc->Flags &= ~VCF_MAKE_CALL_PEND;
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
goto COMPLETE_CALL;
|
|
}
|
|
|
|
AllocCallParms(pVc);
|
|
|
|
if (pVc->IrModemCall)
|
|
{
|
|
ConnectionSpeed = pVc->ConnectionSpeed / 8;
|
|
}
|
|
else
|
|
{
|
|
ConnectionSpeed = IrdaGetConnectionSpeed(pVc->IrdaConnContext) / 8;
|
|
}
|
|
|
|
pVc->pMakeCall->CallMgrParameters->Receive.PeakBandwidth = ConnectionSpeed;
|
|
pVc->pMakeCall->CallMgrParameters->Transmit.PeakBandwidth = ConnectionSpeed;
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Connection speed %d\n", ConnectionSpeed));
|
|
|
|
Status = NdisMCmActivateVc(pVc->NdisVcHandle,
|
|
pVc->pMakeCall);
|
|
|
|
COMPLETE_CALL:
|
|
|
|
NdisMCmMakeCallComplete(Status, pVc->NdisVcHandle, NULL, NULL,
|
|
pVc->pMakeCall);
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
pVc->Flags |= VCF_OPEN;
|
|
REFADD(&pVc->RefCnt, 'NEPO');
|
|
}
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmMakeCallComplete status %X\n", Status));
|
|
}
|
|
|
|
NTSTATUS
|
|
MakeIrdaConnection(
|
|
PRASIR_VC pVc,
|
|
PDEVICELIST pDevList,
|
|
CHAR * ServiceName,
|
|
int ServiceNameLen)
|
|
{
|
|
NTSTATUS Status=STATUS_UNSUCCESSFUL;
|
|
ULONG i;
|
|
TDI_ADDRESS_IRDA IrdaAddr;
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Connect to service %s\n", ServiceName));
|
|
|
|
//
|
|
// Attempt a connection to all devices
|
|
// in range until one succeeds
|
|
//
|
|
|
|
RtlCopyMemory(IrdaAddr.irdaServiceName,
|
|
ServiceName,
|
|
ServiceNameLen);
|
|
|
|
for (i = 0; i < pDevList->numDevice; i++)
|
|
{
|
|
RtlCopyMemory(IrdaAddr.irdaDeviceID,
|
|
pDevList->Device[i].irdaDeviceID, 4);
|
|
|
|
Status = IrdaOpenConnection(&IrdaAddr, pVc, &pVc->IrdaConnContext, FALSE);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Vc %X IrdaOpenConnection() to device %X, Status %X\n",
|
|
pVc, IrdaAddr.irdaDeviceID, Status));
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
IrdaCloseAddresses()
|
|
{
|
|
PRASIR_ADAPTER pAdapter, pNextAdapter;
|
|
|
|
NdisAcquireSpinLock(&RasIrSpinLock);
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Close addresses\n"));
|
|
for (pAdapter = (PRASIR_ADAPTER) RasIrAdapterList.Flink;
|
|
pAdapter != (PRASIR_ADAPTER) &RasIrAdapterList;
|
|
pAdapter = pNextAdapter)
|
|
{
|
|
pNextAdapter = (PRASIR_ADAPTER) pAdapter->Linkage.Flink;
|
|
|
|
NdisReleaseSpinLock(&RasIrSpinLock);
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Close address on adapter %X\n", pAdapter));
|
|
|
|
CloseNextAdapterEndpoint(pAdapter);
|
|
|
|
NdisAcquireSpinLock(&RasIrSpinLock);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&RasIrSpinLock);
|
|
}
|
|
|
|
VOID
|
|
InitiateIrdaConnection(
|
|
IN NDIS_WORK_ITEM *pWork,
|
|
IN VOID *pContext)
|
|
{
|
|
PRASIR_VC pVc = pContext;
|
|
PRASIR_ADAPTER pAdapter;
|
|
NTSTATUS Status;
|
|
CHAR DevListBuf[sizeof(DEVICELIST) - sizeof(IRDA_DEVICE_INFO) +
|
|
(sizeof(IRDA_DEVICE_INFO) * 3)];
|
|
PDEVICELIST pDevList = (PDEVICELIST) DevListBuf;
|
|
ULONG DevListLen = sizeof(DevListBuf);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: InitiateIrdaConnection\n"));
|
|
|
|
GOODVC(pVc);
|
|
|
|
pAdapter = pVc->pAdapter;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
NdisFreeToNPagedLookasideList(&pAdapter->WorkItemsLList, pWork);
|
|
|
|
Status = IrdaDiscoverDevices(pDevList, &DevListLen);
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
goto EXIT;
|
|
}
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: IrdaDiscoverDevices, %d devices found\n",
|
|
pDevList->numDevice));
|
|
|
|
if (pDevList->numDevice == 0)
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: No devices found\n"));
|
|
Status = NDIS_STATUS_TAPI_DISCONNECTMODE_UNREACHABLE;
|
|
goto EXIT;
|
|
}
|
|
|
|
// First attempt a direct connection. if it fails try a phone connection
|
|
|
|
if (pVc->IrModemCall)
|
|
{
|
|
pVc->AsyncFraming = TRUE;
|
|
pVc->ModemState = MS_OFFLINE;
|
|
|
|
Status = MakeIrdaConnection(
|
|
pVc,
|
|
pDevList,
|
|
RASIR_SERVICE_NAME_IRMODEM,
|
|
sizeof(RASIR_SERVICE_NAME_IRMODEM));
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
NdisAllocateBufferPool(&Status,
|
|
&pVc->TxBufferPool,
|
|
TX_BUF_POOL_SIZE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = MakeIrdaConnection(
|
|
pVc,
|
|
pDevList,
|
|
RASIR_SERVICE_NAME_DIRECT,
|
|
sizeof(RASIR_SERVICE_NAME_DIRECT));
|
|
}
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: IrdaOpenConnection failed %X\n", Status));
|
|
Status = NDIS_STATUS_TAPI_DISCONNECTMODE_REJECT;
|
|
}
|
|
else
|
|
{
|
|
pVc->Flags |= VCF_IRDA_OPEN;
|
|
|
|
REFADD(&pVc->RefCnt, 'ADRI');
|
|
}
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS && pVc->IrModemCall)
|
|
{
|
|
PASYNC_BUFFER pAsyncBuf;
|
|
|
|
//
|
|
// Start the IrDial exchange
|
|
//
|
|
|
|
pVc->ModemState = MS_CONNECTING;
|
|
|
|
ASSERT(pVc->pOfflineNdisBuf == NULL);
|
|
|
|
|
|
//
|
|
// Build the phone number string, make sore the buffer is big enough for the atd+number+cr+null
|
|
//
|
|
if (sizeof(pVc->OfflineSendBuf) > pVc->pTmParams->DestAddress.Offset+3+1+1 ) {
|
|
int i;
|
|
char *pIn, *pOut;
|
|
|
|
strcpy(pVc->OfflineSendBuf, "ATD");
|
|
|
|
pOut = pVc->OfflineSendBuf+3;
|
|
|
|
pIn = ((PUCHAR)&(pVc->pTmParams->DestAddress)) + pVc->pTmParams->DestAddress.Offset;
|
|
|
|
// Tapi gives us a UNICODE number so fix it up
|
|
|
|
for (i = 0; i < pVc->pTmParams->DestAddress.Length; i++)
|
|
{
|
|
if (*pIn != 0)
|
|
{
|
|
*pOut++ = *pIn;
|
|
}
|
|
pIn++;
|
|
}
|
|
|
|
*pOut++ = '\r';
|
|
*pOut = 0;
|
|
|
|
} else {
|
|
|
|
Status=STATUS_INVALID_PARAMETER;
|
|
goto EXIT;
|
|
}
|
|
|
|
|
|
NdisAllocateBuffer(&Status, &pVc->pOfflineNdisBuf,
|
|
pVc->TxBufferPool,
|
|
pVc->OfflineSendBuf, strlen(pVc->OfflineSendBuf));
|
|
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
REFADD(&pVc->RefCnt, 'DNES');
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Send dial string vc:%X, packet %X\n",
|
|
pVc, pVc->pOfflineNdisBuf));
|
|
|
|
IrdaSend(pVc->IrdaConnContext, pVc->pOfflineNdisBuf, RASIR_INTERNAL_SEND);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
EXIT:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS && pVc->Flags & VCF_IRDA_OPEN)
|
|
{
|
|
IrdaCloseConnection(pVc->IrdaConnContext);
|
|
}
|
|
|
|
CompleteMakeCall(pVc, Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmMakeCall(
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters,
|
|
IN NDIS_HANDLE NdisPartyHandle,
|
|
OUT PNDIS_HANDLE CallMgrPartyContext)
|
|
{
|
|
PRASIR_VC pVc = CallMgrVcContext;
|
|
PRASIR_ADAPTER pAdapter;
|
|
PCO_SPECIFIC_PARAMETERS pMSpecifics;
|
|
PCO_AF_TAPI_MAKE_CALL_PARAMETERS pTmParams;
|
|
NDIS_STATUS Status = NDIS_STATUS_PENDING;
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmMakeCall\n"));
|
|
|
|
GOODVC(pVc);
|
|
|
|
pAdapter = pVc->pAdapter;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
if (CallParameters->Flags & (PERMANENT_VC | BROADCAST_VC | MULTIPOINT_VC))
|
|
{
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
goto EXIT;
|
|
}
|
|
|
|
if (!CallParameters->MediaParameters)
|
|
{
|
|
Status = NDIS_STATUS_INVALID_DATA;
|
|
goto EXIT;
|
|
}
|
|
|
|
pMSpecifics = &CallParameters->MediaParameters->MediaSpecific;
|
|
if (pMSpecifics->Length < sizeof(CO_AF_TAPI_MAKE_CALL_PARAMETERS))
|
|
{
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
goto EXIT;
|
|
}
|
|
|
|
pTmParams = (CO_AF_TAPI_MAKE_CALL_PARAMETERS* )&pMSpecifics->Parameters;
|
|
|
|
pVc->pMakeCall = CallParameters;
|
|
pVc->pTmParams = pTmParams;
|
|
|
|
if (CallMgrPartyContext)
|
|
{
|
|
*CallMgrPartyContext = NULL;
|
|
}
|
|
|
|
if (pAdapter->ModemPort)
|
|
{
|
|
pVc->IrModemCall = TRUE;
|
|
}
|
|
|
|
pVc->Flags |= VCF_MAKE_CALL_PEND;
|
|
|
|
Status = ScheduleWork(pAdapter, InitiateIrdaConnection, pVc);
|
|
|
|
EXIT:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: RasIrCmMakeCall failed %X\n",
|
|
Status));
|
|
|
|
InterlockedExchangePointer(&pAdapter->NdisSapHandle, NULL);
|
|
|
|
return Status;
|
|
}
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
VOID
|
|
CompleteClose(PRASIR_VC pVc)
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Complete close for vc:%X\n", pVc));
|
|
|
|
REFADD(&pVc->RefCnt, 'DLOH');
|
|
|
|
if (pVc->Flags & VCF_MAKE_CALL_PEND)
|
|
{
|
|
CompleteMakeCall(pVc, NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
if (pVc->Flags & VCF_OPEN)
|
|
{
|
|
NdisMCmDeactivateVc(pVc->NdisVcHandle);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmCloseCallComplete\n"));
|
|
|
|
NdisMCmCloseCallComplete(NDIS_STATUS_SUCCESS,
|
|
pVc->NdisVcHandle, NULL);
|
|
|
|
REFDEL(&pVc->RefCnt, 'NEPO');
|
|
}
|
|
|
|
if (pVc->Flags & VCF_CREATED_LOCAL)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
Status = NdisMCmDeleteVc(pVc->NdisVcHandle);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmDeleteVc returned %X\n",
|
|
Status));
|
|
|
|
RasIrCmDeleteVc((NDIS_HANDLE) pVc);
|
|
}
|
|
|
|
REFDEL(&pVc->RefCnt, 'DLOH');
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Close complete for vc:%X\n", pVc));
|
|
}
|
|
|
|
VOID
|
|
InitiateCloseCall(
|
|
IN NDIS_WORK_ITEM *pWork,
|
|
IN VOID *pContext)
|
|
{
|
|
PRASIR_VC pVc = pContext;
|
|
|
|
NdisFreeToNPagedLookasideList(&pVc->pAdapter->WorkItemsLList, pWork);
|
|
|
|
GOODVC(pVc);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: InitiateCloseCall for vc:%X\n", pVc));
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
if (pVc->Flags & VCF_IRDA_OPEN)
|
|
{
|
|
pVc->Flags &= ~VCF_IRDA_OPEN;
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
ASSERT(pVc->IrdaConnContext);
|
|
|
|
IrdaCloseConnection(pVc->IrdaConnContext);
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
}
|
|
|
|
if (pVc->OutstandingSends)
|
|
{
|
|
pVc->Flags |= VCF_CLOSE_PEND;
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: Outstanding sends, pending close\n"));
|
|
}
|
|
else
|
|
{
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
CompleteClose(pVc);
|
|
}
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmCloseCall(
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN NDIS_HANDLE CallMgrPartyContext,
|
|
IN PVOID CloseData,
|
|
IN UINT Size)
|
|
{
|
|
PRASIR_VC pVc = CallMgrVcContext;
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmCloseCall vc:%X\n", pVc));
|
|
|
|
GOODVC(pVc);
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
if (pVc->Flags & VCF_MAKE_CALL_PEND)
|
|
{
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Make call is pending, not accepting close call\n"));
|
|
|
|
return NDIS_STATUS_NOT_ACCEPTED;
|
|
}
|
|
|
|
pVc->Flags |= VCF_CLOSING;
|
|
|
|
if (!(pVc->Flags & VCF_OPEN) && !(pVc->Flags & VCF_IRDA_OPEN))
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: IrDA and VC not open\n"));
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
ScheduleWork(pVc->pAdapter, InitiateCloseCall, pVc);
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
VOID
|
|
RasIrCmIncomingCallComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN PCO_CALL_PARAMETERS CallParameters)
|
|
{
|
|
PRASIR_VC pVc = CallMgrVcContext;
|
|
PRASIR_ADAPTER pAdapter;
|
|
// WAN_CO_LINKPARAMS WanCoLinkParams;
|
|
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmIncomingCallComplete status %X\n",
|
|
Status));
|
|
|
|
GOODVC(pVc);
|
|
|
|
pAdapter = pVc->pAdapter;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
NdisMCmDeactivateVc(pVc->NdisVcHandle);
|
|
RasIrCmCloseCall(pVc, NULL, NULL, 0);
|
|
return;
|
|
}
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmDispatchCallConnected\n"));
|
|
|
|
NdisMCmDispatchCallConnected(pVc->NdisVcHandle);
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
pVc->Flags |= VCF_OPEN;
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
/* Don't need to do this
|
|
WanCoLinkParams.TransmitSpeed = 4000000;
|
|
WanCoLinkParams.ReceiveSpeed = 4000000;
|
|
WanCoLinkParams.SendWindow = 10;
|
|
|
|
NdisMCoIndicateStatus(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pVc->NdisVcHandle,
|
|
NDIS_STATUS_WAN_CO_LINKPARAMS,
|
|
&WanCoLinkParams,
|
|
sizeof(WanCoLinkParams));
|
|
*/
|
|
|
|
REFADD(&pVc->RefCnt, 'NEPO');
|
|
}
|
|
|
|
VOID
|
|
RasIrCmActivateVcComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN PCO_CALL_PARAMETERS CallParameters)
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmActivateVcComplete\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
RasIrCmDeactivateVcComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE CallMgrVcContext)
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmDeactivateVcComplete\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmModifyCallQoS(
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN PCO_CALL_PARAMETERS CallParameters)
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: RasIrCmModifyCallQos\n"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID
|
|
DeleteVc(
|
|
IN PRASIR_VC pVc)
|
|
{
|
|
|
|
GOODVC(pVc);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Deleting vc:%X\n", pVc));
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
RemoveEntryList(&pVc->Linkage);
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
NdisFreePacketPool(pVc->RxPacketPool);
|
|
|
|
NdisFreeBufferPool(pVc->RxBufferPool);
|
|
|
|
if (pVc->TxBufferPool)
|
|
{
|
|
NdisFreeBufferPool(pVc->TxBufferPool);
|
|
}
|
|
|
|
#if DBG
|
|
pVc->Sig = 0xBAD;
|
|
#endif
|
|
|
|
if (pVc->pInCallParms)
|
|
{
|
|
NdisFreeMemory(pVc->pInCallParms, 0, 0); // yikes, 0 len :)
|
|
}
|
|
|
|
NdisFreeMemory(pVc, 0, 0);
|
|
}
|
|
|
|
NTSTATUS
|
|
IrdaIncomingConnection(
|
|
PVOID ClEndpContext,
|
|
PVOID ConnectionContext,
|
|
PVOID *pClConnContext)
|
|
{
|
|
PRASIR_IRDA_ENDPOINT pEndp = (PRASIR_IRDA_ENDPOINT) ClEndpContext;
|
|
PRASIR_ADAPTER pAdapter;
|
|
PRASIR_VC pVc;
|
|
NDIS_STATUS Status;
|
|
CO_CALL_PARAMETERS* pCp;
|
|
ULONG ConnectionSpeed;
|
|
|
|
GOODENDP(pEndp);
|
|
|
|
pAdapter = pEndp->pAdapter;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: IrdaIncomingConnection, type %d service %s\n",
|
|
pEndp->EndpType, pEndp->ServiceName));
|
|
|
|
Status = RasIrCmCreateVc(pAdapter,
|
|
NULL,
|
|
&pVc);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
goto error1;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
pVc->IrdaConnContext = ConnectionContext;
|
|
pVc->Flags |= VCF_CREATED_LOCAL;
|
|
pVc->AsyncFraming = (pEndp->EndpType == EPT_DIRECT ? FALSE : TRUE);
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
AllocCallParms(pVc);
|
|
|
|
pCp = (CO_CALL_PARAMETERS *) pVc->pInCallParms;
|
|
|
|
if (pVc->pInCallParms == NULL)
|
|
{
|
|
goto error2;
|
|
}
|
|
|
|
if (pVc->AsyncFraming)
|
|
{
|
|
NdisAllocateBufferPool(&Status,
|
|
&pVc->TxBufferPool,
|
|
TX_BUF_POOL_SIZE);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
goto error2;
|
|
}
|
|
}
|
|
|
|
Status = NdisMCmCreateVc(pAdapter->MiniportAdapterHandle,
|
|
pAdapter->NdisAfHandle,
|
|
pVc,
|
|
&pVc->NdisVcHandle);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisMCmCreateVc failed %X\n", Status));
|
|
goto error2;
|
|
}
|
|
|
|
Status = NdisMCmActivateVc(pVc->NdisVcHandle, pCp);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisMCmActivateVc failed %X\n", Status));
|
|
goto error3;
|
|
}
|
|
|
|
ConnectionSpeed = IrdaGetConnectionSpeed(pVc->IrdaConnContext) / 8;
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Connection speed %d\n", ConnectionSpeed));
|
|
|
|
pCp->CallMgrParameters->Receive.PeakBandwidth = ConnectionSpeed;
|
|
pCp->CallMgrParameters->Transmit.PeakBandwidth = ConnectionSpeed;
|
|
|
|
Status = NdisMCmDispatchIncomingCall(pAdapter->NdisSapHandle,
|
|
pVc->NdisVcHandle,
|
|
pCp);
|
|
|
|
if (!(pVc->Flags & VCF_CLOSING))
|
|
{
|
|
pVc->Flags |= VCF_IRDA_OPEN;
|
|
|
|
REFADD(&pVc->RefCnt, 'ADRI');
|
|
|
|
*pClConnContext = pVc;
|
|
|
|
switch (Status)
|
|
{
|
|
case NDIS_STATUS_SUCCESS:
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmDispatchIncomingCall completed synchronously\n"));
|
|
RasIrCmIncomingCallComplete(Status, pVc, NULL);
|
|
return STATUS_SUCCESS;
|
|
|
|
case NDIS_STATUS_PENDING:
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmDispatchIncomingCall returned pending\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: NdisMCmDispatchIncomingCall failed %X\n",
|
|
Status));
|
|
|
|
NdisMCmDeactivateVc(pVc->NdisVcHandle);
|
|
|
|
error3:
|
|
|
|
NdisMCmDeleteVc(pVc->NdisVcHandle);
|
|
|
|
error2:
|
|
|
|
RasIrCmDeleteVc(pVc);
|
|
|
|
error1:
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
VOID
|
|
IrdaConnectionClosed(
|
|
PVOID ConnectionContext)
|
|
{
|
|
PRASIR_VC pVc = ConnectionContext;
|
|
|
|
GOODVC(pVc);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: IrdaConnectionClose vc:%X\n", pVc));
|
|
|
|
NdisAcquireSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
if (!(pVc->Flags & VCF_IRDA_OPEN))
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, (" Irda not open\n"));
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
return;
|
|
}
|
|
|
|
pVc->Flags &= ~VCF_IRDA_OPEN;
|
|
|
|
NdisReleaseSpinLock(&pVc->pAdapter->SpinLock);
|
|
|
|
IrdaCloseConnection(pVc->IrdaConnContext);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: ->NdisMCmDispatchIncomingCloseCall\n"));
|
|
|
|
NdisMCmDispatchIncomingCloseCall(
|
|
NDIS_STATUS_SUCCESS,
|
|
pVc->NdisVcHandle,
|
|
NULL, 0);
|
|
}
|
|
|
|
VOID
|
|
IrdaCloseConnectionComplete(
|
|
PVOID ConnectionContext)
|
|
{
|
|
PRASIR_VC pVc = ConnectionContext;
|
|
|
|
GOODVC(pVc);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: IrdaCloseConnectionComplete vc:%X\n", pVc));
|
|
|
|
REFDEL(&pVc->RefCnt, 'ADRI');
|
|
}
|
|
|
|
VOID
|
|
AllocCallParms(
|
|
IN PRASIR_VC pVc)
|
|
{
|
|
CO_CALL_PARAMETERS* pCp;
|
|
CO_CALL_MANAGER_PARAMETERS* pCmp;
|
|
CO_MEDIA_PARAMETERS* pMp;
|
|
ULONG CallParmsSize;
|
|
CO_AF_TAPI_INCOMING_CALL_PARAMETERS* pTi;
|
|
LINE_CALL_INFO* pLci;
|
|
|
|
|
|
ASSERT(pVc->pInCallParms == NULL);
|
|
|
|
if (pVc->pInCallParms != NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// no attempt here to hide the beauty of CoNdis.
|
|
|
|
CallParmsSize = sizeof(CO_CALL_PARAMETERS) +
|
|
+ sizeof(CO_CALL_MANAGER_PARAMETERS)
|
|
+ sizeof(CO_MEDIA_PARAMETERS)
|
|
+ sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)
|
|
+ sizeof(LINE_CALL_INFO);
|
|
|
|
NdisAllocateMemoryWithTag((PVOID *)&pVc->pInCallParms,
|
|
CallParmsSize, MT_RASIR_CALLPARMS);
|
|
|
|
if (pVc->pInCallParms == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(pVc->pInCallParms, CallParmsSize);
|
|
|
|
pCp = (CO_CALL_PARAMETERS* )pVc->pInCallParms;
|
|
pCmp = (PCO_CALL_MANAGER_PARAMETERS )(pCp + 1);
|
|
pCp->CallMgrParameters = pCmp;
|
|
pCmp->Transmit.TokenRate =
|
|
pCmp->Transmit.PeakBandwidth =
|
|
pCmp->Receive.TokenRate =
|
|
pCmp->Receive.PeakBandwidth = RASIR_MAX_RATE/8;
|
|
|
|
pMp = (PCO_MEDIA_PARAMETERS )(pCmp + 1);
|
|
pCp->MediaParameters = pMp;
|
|
pMp->ReceiveSizeHint = IRDA_MAX_DATA_SIZE;
|
|
pMp->MediaSpecific.Length = sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)
|
|
+ sizeof(LINE_CALL_INFO);
|
|
pTi = (CO_AF_TAPI_INCOMING_CALL_PARAMETERS* )
|
|
pMp->MediaSpecific.Parameters;
|
|
|
|
pTi->ulLineID = 0;
|
|
|
|
pTi->ulAddressID = CO_TAPI_ADDRESS_ID_UNSPECIFIED;
|
|
pTi->ulFlags = CO_TAPI_FLAG_INCOMING_CALL;
|
|
pTi->LineCallInfo.Length = sizeof(LINE_CALL_INFO);
|
|
pTi->LineCallInfo.MaximumLength = sizeof(LINE_CALL_INFO);
|
|
pTi->LineCallInfo.Offset = sizeof(pTi->LineCallInfo);
|
|
|
|
pLci = (LINE_CALL_INFO* )(pTi + 1);
|
|
pLci->ulTotalSize = sizeof(LINE_CALL_INFO);
|
|
pLci->ulNeededSize = sizeof(LINE_CALL_INFO);
|
|
pLci->ulUsedSize = sizeof(LINE_CALL_INFO);
|
|
pLci->ulLineDeviceID = pTi->ulLineID;
|
|
pLci->ulBearerMode = LINEBEARERMODE_DATA;
|
|
pLci->ulMediaMode = LINEMEDIAMODE_DIGITALDATA;
|
|
|
|
pLci->ulRate = RASIR_MAX_RATE;
|
|
|
|
pVc->pTiParams = pTi;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
QueryCmInformation(
|
|
IN PRASIR_ADAPTER pAdapter,
|
|
IN PRASIR_VC pVc,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesWritten,
|
|
OUT PULONG BytesNeeded)
|
|
|
|
// Handle Call Manager QueryInformation requests. Arguments are as for
|
|
// the standard NDIS 'MiniportQueryInformation' handler except this
|
|
// routine does not count on being serialized with respect to other
|
|
// requests.
|
|
//
|
|
{
|
|
NDIS_STATUS Status;
|
|
ULONG ulInfo;
|
|
VOID* pInfo;
|
|
ULONG ulInfoLen;
|
|
ULONG extension;
|
|
ULONG ulPortIndex;
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
// The cases in this switch statement find or create a buffer containing
|
|
// the requested information and point 'pInfo' at it, noting it's length
|
|
// in 'ulInfoLen'. Since many of the OIDs return a ULONG, a 'ulInfo'
|
|
// buffer is set up as the default.
|
|
//
|
|
ulInfo = 0;
|
|
pInfo = &ulInfo;
|
|
ulInfoLen = sizeof(ulInfo);
|
|
|
|
switch (Oid)
|
|
{
|
|
case OID_CO_TAPI_CM_CAPS:
|
|
{
|
|
CO_TAPI_CM_CAPS caps;
|
|
NTSTATUS statusDevice;
|
|
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: QueryCm OID_CO_TAPI_CM_CAPS\n"));
|
|
|
|
NdisZeroMemory( &caps, sizeof(caps) );
|
|
|
|
//
|
|
// Report 2 lines, 1 for phone and 1 for DCC
|
|
//
|
|
caps.ulCoTapiVersion = CO_TAPI_VERSION;
|
|
caps.ulNumLines = 1;
|
|
caps.ulFlags = CO_TAPI_FLAG_PER_LINE_CAPS;
|
|
pInfo = ∩︀
|
|
ulInfoLen = sizeof(caps);
|
|
break;
|
|
}
|
|
|
|
case OID_CO_TAPI_LINE_CAPS:
|
|
{
|
|
RASIR_CO_TAPI_LINE_CAPS RasIrLineCaps;
|
|
CO_TAPI_LINE_CAPS* pInCaps;
|
|
LINE_DEV_CAPS* pldc;
|
|
ULONG ulPortForLineId;
|
|
|
|
if (InformationBufferLength < sizeof(RASIR_CO_TAPI_LINE_CAPS))
|
|
{
|
|
Status = NDIS_STATUS_INVALID_DATA;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
|
|
ASSERT( InformationBuffer );
|
|
|
|
pInCaps = (CO_TAPI_LINE_CAPS* )InformationBuffer;
|
|
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: QueryCm OID_CO_TAPI_LINE_CAPS line %d\n",
|
|
pInCaps->ulLineID));
|
|
|
|
NdisZeroMemory(&RasIrLineCaps, sizeof(RasIrLineCaps));
|
|
pldc = &RasIrLineCaps.caps.LineDevCaps;
|
|
|
|
// get the LineId from the incoming pInCaps (CO_TAPI_LINE_CAPS)
|
|
//
|
|
RasIrLineCaps.caps.ulLineID = pInCaps->ulLineID;
|
|
|
|
pldc->ulPermanentLineID = RasIrLineCaps.caps.ulLineID;
|
|
pldc->ulTotalSize = pInCaps->LineDevCaps.ulTotalSize;
|
|
pldc->ulNeededSize = (ULONG ) ((CHAR* )(&RasIrLineCaps + 1) - (CHAR* )(&RasIrLineCaps.caps.LineDevCaps));
|
|
pldc->ulUsedSize = pldc->ulNeededSize;
|
|
pldc->ulNumAddresses = 1;
|
|
pldc->ulBearerModes = LINEBEARERMODE_DATA;
|
|
pldc->ulMaxRate = RASIR_MAX_RATE;
|
|
pldc->ulMediaModes = LINEMEDIAMODE_UNKNOWN | LINEMEDIAMODE_DIGITALDATA;
|
|
pldc->ulStringFormat = STRINGFORMAT_ASCII;
|
|
pldc->ulLineNameOffset = (ULONG ) ((CHAR* )RasIrLineCaps.LineName - (CHAR* )pldc);
|
|
if (pAdapter->ModemPort)
|
|
{
|
|
pldc->ulMaxNumActiveCalls = 1;
|
|
}
|
|
else
|
|
{
|
|
pldc->ulMaxNumActiveCalls = 4;
|
|
}
|
|
|
|
RtlCopyMemory(RasIrLineCaps.LineName, pAdapter->TapiLineName.Buffer, pAdapter->TapiLineName.Length);
|
|
pldc->ulLineNameSize = pAdapter->TapiLineName.Length;
|
|
|
|
pInfo = &RasIrLineCaps;
|
|
ulInfoLen = sizeof(RasIrLineCaps);
|
|
break;
|
|
}
|
|
|
|
case OID_CO_TAPI_ADDRESS_CAPS:
|
|
{
|
|
CO_TAPI_ADDRESS_CAPS caps;
|
|
CO_TAPI_ADDRESS_CAPS* pInCaps;
|
|
LINE_ADDRESS_CAPS* plac;
|
|
|
|
if (InformationBufferLength < sizeof(CO_TAPI_ADDRESS_CAPS))
|
|
{
|
|
Status = NDIS_STATUS_INVALID_DATA;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
|
|
ASSERT( InformationBuffer );
|
|
pInCaps = (CO_TAPI_ADDRESS_CAPS* )InformationBuffer;
|
|
|
|
NdisZeroMemory( &caps, sizeof(caps) );
|
|
|
|
caps.ulLineID = pInCaps->ulLineID;
|
|
caps.ulAddressID = pInCaps->ulAddressID;
|
|
|
|
plac = &caps.LineAddressCaps;
|
|
|
|
if (pAdapter->ModemPort)
|
|
{
|
|
plac->ulAddrCapFlags = LINEADDRCAPFLAGS_DIALED;
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: QueryCm OID_CO_TAPI_ADDRESS_CAPS line %d address %d, DIALED\n",
|
|
pInCaps->ulLineID, pInCaps->ulAddressID));
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: QueryCm OID_CO_TAPI_ADDRESS_CAPS line %d address %d, DCC\n",
|
|
pInCaps->ulLineID, pInCaps->ulAddressID));
|
|
}
|
|
|
|
|
|
plac->ulTotalSize = sizeof(LINE_ADDRESS_CAPS);
|
|
plac->ulNeededSize = sizeof(LINE_ADDRESS_CAPS);
|
|
plac->ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
|
|
plac->ulLineDeviceID = caps.ulLineID;
|
|
plac->ulMaxNumActiveCalls = 64;
|
|
|
|
pInfo = ∩︀
|
|
ulInfoLen = sizeof(caps);
|
|
break;
|
|
}
|
|
|
|
case OID_CO_TAPI_GET_CALL_DIAGNOSTICS:
|
|
{
|
|
CO_TAPI_CALL_DIAGNOSTICS diags;
|
|
|
|
DEBUGMSG(DBG_CONFIG, ("RASIR: QueryCm OID_CO_TAPI_GET_CALL_DIAGS\n"));
|
|
|
|
if (!pVc)
|
|
{
|
|
Status = NDIS_STATUS_INVALID_DATA;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
|
|
NdisZeroMemory( &diags, sizeof(diags) );
|
|
|
|
diags.ulOrigin = pVc->Flags & VCF_CREATED_LOCAL ?
|
|
LINECALLORIGIN_EXTERNAL : LINECALLORIGIN_OUTBOUND;
|
|
|
|
diags.ulReason = LINECALLREASON_DIRECT;
|
|
|
|
pInfo = &diags;
|
|
ulInfoLen = sizeof(diags);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: QueryCm OID not supported %X\n", Oid));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ulInfoLen > InformationBufferLength)
|
|
{
|
|
// Caller's buffer is too small. Tell him what he needs.
|
|
//
|
|
*BytesNeeded = ulInfoLen;
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
// Copy the found result to caller's buffer.
|
|
//
|
|
if (ulInfoLen > 0)
|
|
{
|
|
NdisMoveMemory( InformationBuffer, pInfo, ulInfoLen );
|
|
}
|
|
|
|
*BytesNeeded = *BytesWritten = ulInfoLen;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
RasIrCmRequest(
|
|
IN NDIS_HANDLE CallMgrAfContext,
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN NDIS_HANDLE CallMgrPartyContext,
|
|
IN OUT PNDIS_REQUEST NdisRequest )
|
|
|
|
// Standard 'CmRequestHandler' routine called by NDIS in response to a
|
|
// client's request for information from the mini-port.
|
|
//
|
|
{
|
|
PRASIR_ADAPTER pAdapter = (PRASIR_ADAPTER) CallMgrAfContext;
|
|
PRASIR_VC pVc = (PRASIR_VC) CallMgrVcContext;
|
|
NDIS_STATUS Status;
|
|
|
|
GOODADAPTER(pAdapter);
|
|
|
|
if (pVc)
|
|
{
|
|
GOODVC(pVc);
|
|
}
|
|
|
|
switch (NdisRequest->RequestType)
|
|
{
|
|
case NdisRequestQueryInformation:
|
|
{
|
|
Status = QueryCmInformation(
|
|
pAdapter,
|
|
pVc,
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
|
|
&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded );
|
|
break;
|
|
}
|
|
|
|
case NdisRequestSetInformation:
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: RasIrCmRequest - NdisRequestSetInformation not supported\n"));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("RASIR: RasIrCmRequest - Request type %d not supported\n",
|
|
NdisRequest->RequestType));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
ProcessOfflineRxBuf(
|
|
IN PRASIR_VC pVc,
|
|
IN PIRDA_RECVBUF pRecvBuf)
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
|
|
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Offline command received. buflen %d %c%c%c%c\n",
|
|
pRecvBuf->BufLen, pRecvBuf->Buf[2], pRecvBuf->Buf[3],
|
|
pRecvBuf->Buf[4], pRecvBuf->Buf[5]));
|
|
|
|
if (pRecvBuf->BufLen < 3)
|
|
{
|
|
goto EXIT;
|
|
}
|
|
|
|
if (pVc->ModemState == MS_CONNECTING)
|
|
{
|
|
|
|
if (pRecvBuf->Buf[2] == 'C') // "<CR><LF>CONNECT 9600<CR><LF>"
|
|
{
|
|
pVc->ModemState = MS_ONLINE;
|
|
|
|
// Extract the baudrate
|
|
|
|
if (pRecvBuf->BufLen > 13)
|
|
{
|
|
// Replace <CR><LF> with 0
|
|
|
|
pRecvBuf->Buf[pRecvBuf->BufLen-1] = 0;
|
|
pRecvBuf->Buf[pRecvBuf->BufLen-2] = 0;
|
|
|
|
pVc->ConnectionSpeed = 2400;
|
|
|
|
RtlCharToInteger(&pRecvBuf->Buf[10], 10, &pVc->ConnectionSpeed);
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: Modem connected at %d\n",
|
|
pVc->ConnectionSpeed));
|
|
|
|
}
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
else if (pRecvBuf->Buf[0] == 'A') // "ATD123-4567<CR>"
|
|
{
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: command echo received\n"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (pRecvBuf->Buf[2] == 'N') // "<CR><LF>NO CARRIER<CR><LF>
|
|
{
|
|
Status = NDIS_STATUS_TAPI_DISCONNECTMODE_NOANSWER;
|
|
}
|
|
|
|
DEBUGMSG(DBG_CONNECT, ("RASIR: IrDial failed\n"));
|
|
pVc->ModemState = MS_OFFLINE;
|
|
}
|
|
}
|
|
|
|
EXIT:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
IrdaCloseConnection(pVc->IrdaConnContext);
|
|
}
|
|
|
|
CompleteMakeCall(pVc, Status);
|
|
}
|