Windows-Server-2003/net/irda/rasirda/callmgr.c

1841 lines
52 KiB
C
Raw Permalink Normal View History

2024-08-04 01:28:15 +02:00
/*++
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 = &caps;
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 = &caps;
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);
}