📄 tdiup.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name: TdiUp.c
Abstract: Contains interface from IrLMP up to TDI.
Contents:
--*/
#include "irdatdi.h"
extern BOOL AutoSuspend;
DWORD g_cActiveConnections = 0;
//
// Allow auto suspend while sockets are opened but there are no active connections.
//
void IrdaAutoSuspend(BOOL bAddConn)
{
BOOL bCallCxport;
if (TRUE == AutoSuspend) {
bCallCxport = FALSE;
EnterCriticalSection(&csIrObjList);
if (bAddConn) {
if (0 == g_cActiveConnections) {
//
// Only call the cxport function to disable suspend
// if the number of active connections goes from 0 to 1.
//
bCallCxport = TRUE;
}
g_cActiveConnections++;
} else{
ASSERT(g_cActiveConnections);
g_cActiveConnections--;
if (0 == g_cActiveConnections) {
//
// Only call the cxport function to enable suspend
// if the number of active connections goes from 1 to 0.
//
bCallCxport = TRUE;
}
}
LeaveCriticalSection(&csIrObjList);
if (bCallCxport) {
CTEIOControl(
bAddConn ? CTE_IOCTL_SET_IDLE_TIMER_RESET : CTE_IOCTL_CLEAR_IDLE_TIMER_RESET,
NULL, 0, NULL, 0, NULL);
}
}
} // IrdaAutoSuspend
/*++
Function: IrlmpDiscoveryConf
Description: Processes an IRLMP_DISCOVERY_CONFIRM. Completes a client
discovery request. The discovery request is stored in
globals data.
Comments:
--*/
VOID
IrlmpDiscoveryConf(IRDA_MSG *pIrDAMsg)
{
IRDA_DEVICE *pIrDADevice;
int NickNameByte;
int NumDevices;
DWORD OldPermissions;
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DISCOVERY_CONF\r\n")));
EnterCriticalSection(&csDscv);
if (DscvInProgress) {
OldPermissions = SetProcPermissions(DscvCallersPermissions);
pIrDADevice = (IRDA_DEVICE *) pIrDAMsg->IRDA_MSG_pDevList->Flink;
if (pIrDAMsg->IRDA_MSG_pDevList == (LIST_ENTRY *) pIrDADevice)
{
NumDevices = 0;
}
else
{
NumDevices = 1;
while (pIrDAMsg->IRDA_MSG_pDevList != (LIST_ENTRY *) pIrDADevice &&
NumDevices <= DscvNumDevices)
{
memcpy(&pDscvDevList->Device[NumDevices - 1].irdaDeviceID[0],
&pIrDADevice->DevAddr[0], IRDA_DEV_ADDR_LEN);
// Retrieve the first 2 hint bytes
pDscvDevList->Device[NumDevices-1].irdaDeviceHints1 = pIrDADevice->DscvInfo[0];
pDscvDevList->Device[NumDevices-1].irdaDeviceHints2 = pIrDADevice->DscvInfo[1];
// Skip additional hint bytes.
NickNameByte = 0;
while (pIrDADevice->DscvInfo[NickNameByte++] & 0x80);
// Get the char set byte
pDscvDevList->Device[NumDevices-1].irdaCharSet = pIrDADevice->DscvInfo[NickNameByte++];
// copy the nickame
memcpy(pDscvDevList->Device[NumDevices-1].irdaDeviceName, &(pIrDADevice->DscvInfo[NickNameByte]), IRDA_MAX_DEVICE_NAME);
pDscvDevList->numDevice = NumDevices++;
pIrDADevice = (IRDA_DEVICE *) pIrDADevice->Linkage.Flink;
}
}
SetProcPermissions(OldPermissions);
SetEvent(DscvConfEvent);
}
LeaveCriticalSection(&csDscv);
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_DISCOVERY_CONF\r\n")));
return;
}
/*++
Function: IrlmpDiscoveryInd
Description: Process an IRLMP_DISCOVERY_IND.
Comments:
--*/
__inline VOID
IrlmpDiscoveryInd()
{
// Release all threads waiting on the DiscoveryIndication
DEBUGMSG (ZONE_TDI, (TEXT("IRLMP_DISCOVERY_IND\r\n")));
SetEvent(DscvIndEvent);
// This is a manual reset event. Anyone who wants to wait for the next
// DISCOVERY_IND should reset the event before leaving the critical
// section and doing the WaitForSingleObject()
}
/*++
Function: IrlmpConnectInd
Description: Processes an IRLMP_CONNECT_IND. Calls client connect
handler if we can find a matching address object.
Comments:
--*/
VOID
IrlmpConnectInd(IRDA_MSG *pIrDAMsg)
{
IRDA_MSG IrDAMsg;
TDI_STATUS TdiStatus;
int rc;
int i;
// IRLMP_CONNECT_IND
BYTE RemAddrBuf[sizeof(TRANSPORT_ADDRESS) +
sizeof(SOCKADDR_IRDA) - 3];
PTRANSPORT_ADDRESS pRemAddr = (PTRANSPORT_ADDRESS) RemAddrBuf;
PSOCKADDR_IRDA pSockAddr;
void *pConnectionContext;
ConnectEventInfo EventConnectCompleteInfo;
int Val, Digit;
char TmpStr[4];
int StrLen;
PIRLMP_ADDR_OBJ pAddrObj = NULL;
PIRLMP_CONNECTION pConn = NULL;
PLIST_ENTRY pAddrEntry, pConnEntry;
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_CONNECT_IND\r\n")));
EnterCriticalSection(&csIrObjList);
for (pAddrEntry = IrAddrObjList.Flink;
pAddrEntry != &IrAddrObjList;
pAddrEntry = pAddrEntry->Flink)
{
if (((PIRLMP_ADDR_OBJ)pAddrEntry)->LSAPSelLocal == pIrDAMsg->IRDA_MSG_LocalLsapSel)
{
pAddrObj = (PIRLMP_ADDR_OBJ)pAddrEntry;
REFADDADDR(pAddrObj);
VALIDADDR(pAddrObj);
break;
}
}
LeaveCriticalSection(&csIrObjList);
if (NULL == pAddrObj)
{
//
// No such address
//
IrDAMsg.Prim = IRLMP_DISCONNECT_REQ;
IrDAMsg.IRDA_MSG_pDiscData = NULL;
IrDAMsg.IRDA_MSG_DiscDataLen = 0;
rc = IrlmpDown(pIrDAMsg->IRDA_MSG_pContext, &IrDAMsg);
ASSERT(rc == 0);
goto done;
}
if (NULL == pAddrObj->pEventConnect)
{
//
// Address not ready for connections (listen not called yet)
//
goto done;
}
pRemAddr->TAAddressCount = 1;
pRemAddr->Address[0].AddressLength = sizeof(SOCKADDR_IRDA) - 2;
pSockAddr = (PSOCKADDR_IRDA) &pRemAddr->Address[0].AddressType;
pSockAddr->irdaAddressFamily = AF_IRDA;
memcpy(&pSockAddr->irdaDeviceID[0],
&pIrDAMsg->IRDA_MSG_RemoteDevAddr[0],
IRDA_DEV_ADDR_LEN);
Val = pIrDAMsg->IRDA_MSG_RemoteLsapSel;
StrLen = 0;
while (Val > 0 && StrLen < 3)
{
Digit = Val % 10;
Val = Val / 10;
TmpStr[StrLen] = Digit + '0';
StrLen++;
}
memcpy(&pSockAddr->irdaServiceName[0], LSAPSEL_TXT, LSAPSEL_TXTLEN);
for (i = 0; i < StrLen; i++)
{
pSockAddr->irdaServiceName[i + 8] = TmpStr[StrLen - 1 - i];
}
pSockAddr->irdaServiceName[StrLen + 8] = 0;
TdiStatus = pAddrObj->pEventConnect(
pAddrObj->pEventConnectContext,
offsetof(TRANSPORT_ADDRESS,
Address[0].AddressType) +
sizeof(SOCKADDR_IRDA),
pRemAddr,
0, NULL, 0, NULL,
&pConnectionContext,
&EventConnectCompleteInfo);
if (TdiStatus != TDI_MORE_PROCESSING)
{
// The only error that we expect?
ASSERT(TdiStatus == STATUS_REQUEST_NOT_ACCEPTED);
goto done;
}
EnterCriticalSection(&csIrObjList);
for (pConnEntry = pAddrObj->ConnList.Flink;
pConnEntry != &pAddrObj->ConnList;
pConnEntry = pConnEntry->Flink)
{
if (((PIRLMP_CONNECTION)pConnEntry)->pConnectionContext == pConnectionContext)
{
pConn = (PIRLMP_CONNECTION)pConnEntry;
REFADDCONN(pConn);
VALIDCONN(pConn);
break;
}
}
LeaveCriticalSection(&csIrObjList);
if (pConn == NULL)
{
IrDAMsg.Prim = IRLMP_DISCONNECT_REQ;
IrDAMsg.IRDA_MSG_pDiscData = NULL;
IrDAMsg.IRDA_MSG_DiscDataLen = 0;
rc = IrlmpDown(pIrDAMsg->IRDA_MSG_pContext, &IrDAMsg);
ASSERT(rc == 0);
EventConnectCompleteInfo.cei_rtn(
EventConnectCompleteInfo.cei_context,
TDI_NO_FREE_ADDR,
0);
goto done;
}
GET_CONN_LOCK(pConn);
ASSERT(pConn->ConnState == IRLMP_CONN_CREATED);
pConn->ConnState = IRLMP_CONN_OPEN;
pConn->LSAPSelRemote = pIrDAMsg->IRDA_MSG_RemoteLsapSel;
pConn->SendMaxSDU = pIrDAMsg->IRDA_MSG_MaxSDUSize;
pConn->SendMaxPDU = pIrDAMsg->IRDA_MSG_MaxPDUSize;
pConn->pIrLMPContext = pIrDAMsg->IRDA_MSG_pContext;
pConn->TinyTPRecvCreditsLeft = TINY_TP_RECV_CREDITS;
// IRDA_MSG_pQos ignored
memcpy(&pConn->SockAddrRemote, pSockAddr, sizeof(SOCKADDR_IRDA));
FREE_CONN_LOCK(pConn);
IrdaAutoSuspend(TRUE); // new active connection
IrDAMsg.Prim = IRLMP_CONNECT_RESP;
IrDAMsg.IRDA_MSG_pConnData = NULL;
IrDAMsg.IRDA_MSG_ConnDataLen = 0;
IrDAMsg.IRDA_MSG_pContext = pConn;
IrDAMsg.IRDA_MSG_MaxSDUSize = TINY_TP_RECV_MAX_SDU;
IrDAMsg.IRDA_MSG_TtpCredits = TINY_TP_RECV_CREDITS;
rc = IrlmpDown(pIrDAMsg->IRDA_MSG_pContext, &IrDAMsg);
ASSERT(rc == 0);
EventConnectCompleteInfo.cei_rtn(
EventConnectCompleteInfo.cei_context,
TDI_SUCCESS,
0);
done:
if (pAddrObj) REFDELADDR(pAddrObj);
if (pConn) REFDELCONN(pConn);
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_CONNECT_IND\r\n")));
return;
}
extern void
LingerTimerFunc(
CTEEvent * pCTEEvent,
void * pContext
);
/*++
Function: IrlmpDisconnectInd
Description: Processes an IRLMP_DISCONNECT_IND.
Comments:
--*/
VOID
IrlmpDisconnectInd(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
TDI_STATUS TdiStatus;
PIRLMP_CONNECTION pConn;
BOOL fConnPending;
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DISCONNECT_IND\r\n")));
pConn = GETCONN(pConnContext);
if (pConn == NULL)
{
DEBUGMSG(ZONE_WARN,
(TEXT("IrlmpDisconnectInd - invalid connection handle.\r\n")));
return;
}
VALIDCONN(pConn);
GET_CONN_LOCK(pConn);
DEBUGMSG(ZONE_WARN,
(TEXT("Got IrLMP Disconnect IND: ConnState=%d DiscReason=%d\r\n"),
pConn->ConnState, pIrDAMsg->IRDA_MSG_DiscReason)
);
//
// Make IRLMP_Disconnect quit its disconnect process because a disconnect indication
// from the peer makes the LsapCb go away no matter what the connection state.
//
pConn->pIrLMPContext = NULL;
if (pConn->ConnState == IRLMP_CONN_OPENING)
{
switch (pIrDAMsg->IRDA_MSG_DiscReason)
{
case IRLMP_MAC_MEDIA_BUSY:
DEBUGMSG(ZONE_WARN, (TEXT("GOT IRLMP_MAC_MEDIA_BUSY in TDI:TdiUp\r\n")));
/* wmz retry the connect */
TdiStatus = TDI_NET_DOWN;
break;
case IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS:
/* wmz retry the connect after DISCOVERY_IND */
DEBUGMSG(ZONE_WARN, (TEXT("GOT IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS in TDI:TdiUp\r\n")));
TdiStatus = TDI_NET_DOWN;
break;
case IRLMP_DISC_LSAP:
TdiStatus = TDI_CONN_REFUSED;
break;
case IRLMP_NO_RESPONSE_LSAP:
TdiStatus = TDI_TIMED_OUT;
break;
default:
TdiStatus = TDI_CONNECTION_ABORTED;
break;
}
fConnPending = pConn->fConnPending;
pConn->fConnPending = FALSE;
pConn->ConnState = IRLMP_CONN_CLOSING;
FREE_CONN_LOCK(pConn);
if (fConnPending && pConn->pConnectCompleteContext) {
pConn->pConnectComplete(pConn->pConnectCompleteContext,
TdiStatus, 0);
// IRLMP_Connect left us an extra ref to take care of.
REFDELCONN(pConn);
}
}
else if (pConn->ConnState == IRLMP_CONN_OPEN)
{
switch (pIrDAMsg->IRDA_MSG_DiscReason)
{
case IRLMP_USER_REQUEST:
TdiStatus = TDI_DISCONNECT_WAIT;
break;
case IRLMP_UNEXPECTED_IRLAP_DISC:
if (pConn->UseSharpMode)
{
// If special sharp mode is set then
// we pretend that an IRLAP_DISC is really
// just a normal close.
// Major hack but there are a lot of Zaurus's
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -