📄 irlmp.c
字号:
// OK to request exclusive mode from peer
pIrlmpCb->pExclLsapCb = pRequestingLsapCb;
if (pMsg->IRDA_MSG_IrLPTMode == TRUE)
{
pMsg->Prim = IRLMP_ACCESSMODE_CONF;
pMsg->IRDA_MSG_AccessMode = IRLMP_EXCLUSIVE;
pMsg->IRDA_MSG_ModeStatus = IRLMP_ACCESSMODE_SUCCESS;
TdiUp(pRequestingLsapCb->pTdiContext, pMsg);
return SUCCESS;
}
else
{
pRequestingLsapCb->State = LSAP_EXCLUSIVEMODE_PEND;
SendCntlPdu(pRequestingLsapCb, IRLMP_ACCESSMODE_PDU,
IRLMP_ABIT_REQUEST, IRLMP_RSVD_PARM,
IRLMP_EXCLUSIVE);
IrdaTimerRestart(&pRequestingLsapCb->ResponseTimer);
}
break;
case IRLMP_MULTIPLEXED:
if (pIrlmpCb->pExclLsapCb == NULL)
{
return IRLMP_IN_MULTIPLEXED_MODE;
}
if (pIrlmpCb->pExclLsapCb != pRequestingLsapCb)
{
return IRLMP_NOT_LSAP_IN_EXCLUSIVE_MODE;
}
if (pMsg->IRDA_MSG_IrLPTMode == TRUE)
{
pIrlmpCb->pExclLsapCb = NULL;
pMsg->Prim = IRLMP_ACCESSMODE_CONF;
pMsg->IRDA_MSG_AccessMode = IRLMP_MULTIPLEXED;
pMsg->IRDA_MSG_ModeStatus = IRLMP_ACCESSMODE_SUCCESS;
return TdiUp(pRequestingLsapCb->pTdiContext,
pMsg);
}
else
{
pRequestingLsapCb->State = LSAP_MULTIPLEXEDMODE_PEND;
SendCntlPdu(pRequestingLsapCb, IRLMP_ACCESSMODE_PDU,
IRLMP_ABIT_REQUEST, IRLMP_RSVD_PARM,
IRLMP_MULTIPLEXED);
IrdaTimerRestart(&pRequestingLsapCb->ResponseTimer);
}
break;
default:
return IRLMP_BAD_ACCESSMODE;
}
return SUCCESS;
}
/*****************************************************************************
*
* @func UINT | SendCntlPdu | Sends connect request to IRLAP
*
* @rdesc SUCCESS or an error code
*
* @parm IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*/
VOID
SendCntlPdu(IRLMP_LSAP_CB *pLsapCb, int OpCode, int ABit,
int Parm1, int Parm2)
{
IRDA_MSG *pMsg = AllocIrdaBuf(IrdaMsgPool);
IRLMP_HEADER *pLMHeader;
IRLMP_CNTL_FORMAT *pCntlFormat;
TTP_CONN_HEADER *pTTPHeader;
TTP_CONN_PARM *pTTPParm;
UINT rc = SUCCESS;
VALIDLSAP(pLsapCb);
if (pMsg == NULL)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Alloc failed\n")));
ASSERT(0);
return;// IRLMP_ALLOC_FAILED;
}
pMsg->IRDA_MSG_SegFlags = SEG_LOCAL | SEG_FINAL;
// Initialize the header pointers to the end of the header block
pMsg->IRDA_MSG_pHdrRead =
pMsg->IRDA_MSG_pHdrWrite = pMsg->IRDA_MSG_Header + IRDA_HEADER_LEN;
// Back up the read pointer for the LMP header
pMsg->IRDA_MSG_pHdrRead -= (sizeof(IRLMP_HEADER) + \
sizeof(IRLMP_CNTL_FORMAT));
// move it forward for non access mode control requests
// (connect and disconnect don't have a Parm2)
if (OpCode != IRLMP_ACCESSMODE_PDU)
{
pMsg->IRDA_MSG_pHdrRead++;
}
// If using Tiny TPP back up the read pointer for its header
// From LMPs point of view this is where the user data begins.
// We are sticking it in the header because TTP is now part of IRLMP.
// TTP connect PDU's are only used for connection establishment
if (pLsapCb->UseTtp && OpCode == IRLMP_CONNECT_PDU)
{
pMsg->IRDA_MSG_pHdrRead -= sizeof(TTP_CONN_HEADER);
if (pLsapCb->RxMaxSDUSize > 0)
{
pMsg->IRDA_MSG_pHdrRead -= sizeof(TTP_CONN_PARM);
}
}
// Build the IRLMP header
pLMHeader = (IRLMP_HEADER *) pMsg->IRDA_MSG_pHdrRead;
pLMHeader->DstLsapSel = pLsapCb->RemoteLsapSel;
pLMHeader->SrcLsapSel = pLsapCb->LocalLsapSel;
pLMHeader->CntlBit = IRLMP_CNTL_PDU;
pLMHeader->RsvrdBit = 0;
// Control portion of header
pCntlFormat = (IRLMP_CNTL_FORMAT *) (pLMHeader + 1);
pCntlFormat->OpCode = OpCode;
pCntlFormat->ABit = ABit;
pCntlFormat->Parm1 = Parm1;
if (OpCode == IRLMP_ACCESSMODE_PDU)
{
pCntlFormat->Parm2 = Parm2; // Access mode
}
// Build the TTP header if needed (we are using TTP and this is a
// connection request or confirmation not).
if (pLsapCb->UseTtp && OpCode == IRLMP_CONNECT_PDU)
{
// Always using the MaxSDUSize parameter. If the client wishes
// to disable, MaxSDUSize = 0
pTTPHeader = (TTP_CONN_HEADER *) (pCntlFormat + 1) - 1;
// -1, LM-Connect-PDU doesn't use parm2
/*
#define TTP_PFLAG_NO_PARMS 0
#define TTP_PFLAG_PARMS 1
*/
pTTPHeader->ParmFlag = (pLsapCb->RxMaxSDUSize > 0);
pTTPHeader->InitialCredit = pLsapCb->RemoteTxCredit;
pTTPParm = (TTP_CONN_PARM *) (pTTPHeader + 1);
if (pLsapCb->RxMaxSDUSize > 0)
{
// HARDCODE-O-RAMA
pTTPParm->PLen = 6;
pTTPParm->PI = TTP_MAX_SDU_SIZE_PI;
pTTPParm->PL = TTP_MAX_SDU_SIZE_PL;
pTTPParm->PV[3] = (UCHAR) (pLsapCb->RxMaxSDUSize & 0xFF);
pTTPParm->PV[2] = (UCHAR) ((pLsapCb->RxMaxSDUSize & 0xFF00)
>> 8);
pTTPParm->PV[1] = (UCHAR) ((pLsapCb->RxMaxSDUSize & 0xFF0000)
>> 16);
pTTPParm->PV[0] = (UCHAR) ((pLsapCb->RxMaxSDUSize & 0xFF000000)
>> 24);
}
}
// Client connection data, Access mode does not include client data
if (pLsapCb->UserDataLen == 0 || OpCode == IRLMP_ACCESSMODE_PDU)
{
pMsg->IRDA_MSG_pBase =
pMsg->IRDA_MSG_pRead =
pMsg->IRDA_MSG_pWrite =
pMsg->IRDA_MSG_pLimit = NULL;
}
else
{
pMsg->IRDA_MSG_pBase = pLsapCb->UserData;
pMsg->IRDA_MSG_pRead = pLsapCb->UserData;
pMsg->IRDA_MSG_pWrite = pLsapCb->UserData + pLsapCb->UserDataLen;
pMsg->IRDA_MSG_pLimit = pMsg->IRDA_MSG_pWrite;
}
// Message built, send data request to IRLAP
pMsg->Prim = IRLAP_DATA_REQ;
pMsg->IRDA_MSG_pOwner = 0;
DEBUGMSG(DBG_IRLMP,(TEXT("IRLMP: Sending LM_%s_%s for l=%d,r=%d pMsg:%X LsapCb:%X\n"),
(OpCode == IRLMP_CONNECT_PDU ? TEXT("CONNECT") :
OpCode == IRLMP_DISCONNECT_PDU ? TEXT("DISCONNECT") :
OpCode == IRLMP_ACCESSMODE_PDU ? TEXT("ACCESSMODE") :
TEXT("!!oops!!")),
(ABit==IRLMP_ABIT_REQUEST?TEXT("REQ"):TEXT("CONF")),
pLsapCb->LocalLsapSel,
pLsapCb->RemoteLsapSel,
pMsg, pLsapCb));
IrlapDown(pLsapCb->pIrlmpCb->pIrdaLinkCb->IrlapContext, pMsg);
}
/*****************************************************************************
*
* @func UINT | LsapResponseTimerExp | Timer expiration callback
*
* @rdesc SUCCESS or an error code
*
*/
VOID
LsapResponseTimerExp(PVOID Context)
{
IRLMP_LSAP_CB *pLsapCb = (IRLMP_LSAP_CB *) Context;
IRDA_MSG IMsg;
UINT rc = SUCCESS;
PIRLMP_LINK_CB pIrlmpCb = pLsapCb->pIrlmpCb;
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: LSAP timer expired\n")));
VALIDLSAP(pLsapCb);
switch (pLsapCb->State)
{
case LSAP_LMCONN_CONF_PEND:
if (pLsapCb->LocalLsapSel == IAS_LSAP_SEL)
{
IasServerDisconnectReq(pLsapCb);
break;
}
if (pLsapCb->LocalLsapSel == IAS_LOCAL_LSAP_SEL &&
pLsapCb->RemoteLsapSel == IAS_LSAP_SEL)
{
IasClientDisconnectReq(pLsapCb, IRLMP_NO_RESPONSE_LSAP) ;
}
else
{
// Tell upper layer the connect request failed
IMsg.Prim = IRLMP_DISCONNECT_IND;
IMsg.IRDA_MSG_DiscReason = IRLMP_NO_RESPONSE_LSAP;
TdiUp(pLsapCb->pTdiContext, &IMsg);
IrdaTimerRestart(&pIrlmpCb->DiscDelayTimer);
CleanupLsap(pLsapCb);
}
break;
case LSAP_CONN_RESP_PEND:
pLsapCb->UserDataLen = 0; // This will ensure no client data sent in
// Disconnect PDU below
// Tell remote LSAP that its peer did not respond
SendCntlPdu(pLsapCb,IRLMP_DISCONNECT_PDU,IRLMP_ABIT_REQUEST,
IRLMP_NO_RESPONSE_LSAP, 0);
IrdaTimerRestart(&pIrlmpCb->DiscDelayTimer);
CleanupLsap(pLsapCb);
break;
case LSAP_MULTIPLEXEDMODE_PEND:
// Spec says peer can't refuse request to return to multiplex mode
// but if no answer, go into multiplexed anyway?
case LSAP_EXCLUSIVEMODE_PEND:
pIrlmpCb->pExclLsapCb = NULL;
// Peer didn't respond, maybe we are not connected anymore ???
pLsapCb->State = LSAP_READY;
IMsg.Prim = IRLMP_ACCESSMODE_CONF;
IMsg.IRDA_MSG_AccessMode = IRLMP_MULTIPLEXED;
IMsg.IRDA_MSG_ModeStatus = IRLMP_ACCESSMODE_FAILURE;
TdiUp(pLsapCb->pTdiContext, &IMsg);
break;
default:
DEBUGMSG(DBG_IRLMP, (TEXT("Ignoring timer expiry in this state\n")));
; // ignore
}
}
/*****************************************************************************
*
* @func UINT | IrlmpUp | Bottom of IRLMP, called by IRLAP with
* IRLAP messages. This is the MUX
*
* @rdesc SUCCESS or an error code
*
*/
UINT
IrlmpUp(PIRDA_LINK_CB pIrdaLinkCb, IRDA_MSG *pMsg)
{
PIRLMP_LINK_CB pIrlmpCb;
if (NULL == pIrdaLinkCb) {
return IRLMP_LINK_BAD_STATE;
}
pIrlmpCb = (PIRLMP_LINK_CB) pIrdaLinkCb->IrlmpContext;
switch (pMsg->Prim)
{
case IRLAP_DISCOVERY_IND:
DEBUGMSG(ZONE_DSCV, (TEXT("IRLAP_DISCOVERY_IND\r\n")));
UpdateDeviceList(pIrdaLinkCb, pMsg->IRDA_MSG_pDevList);
pMsg->Prim = IRLMP_DISCOVERY_IND;
pMsg->IRDA_MSG_pDevList = &DeviceList;
TdiUp(NULL, pMsg);
return SUCCESS;
case IRLAP_DISCOVERY_CONF:
IrlapDiscoveryConf(pIrlmpCb, pMsg);
return SUCCESS;
case IRLAP_CONNECT_IND:
IrlapConnectInd(pIrlmpCb, pMsg);
return SUCCESS;
case IRLAP_CONNECT_CONF:
IrlapConnectConf(pIrlmpCb, pMsg);
return SUCCESS;
case IRLAP_DISCONNECT_IND:
IrlapDisconnectInd(pIrlmpCb, pMsg);
return SUCCESS;
case IRLAP_DATA_CONF:
IrlapDataConf(pMsg);
return SUCCESS;
case IRLAP_DATA_IND:
IrlapDataInd(pIrlmpCb, pMsg);
if (pIrlmpCb->pExclLsapCb &&
pIrlmpCb->pExclLsapCb->RemoteTxCredit <=0)
return IRLMP_LOCAL_BUSY;
else
return SUCCESS;
case IRLAP_UDATA_IND:
ASSERT(0);
return SUCCESS;
case IRLAP_STATUS_IND:
TdiUp(NULL, pMsg);
return SUCCESS;
}
return (SUCCESS);
}
/*****************************************************************************
*
* @func UINT | IrlapDiscoveryConf | Process the discovery confirm
*/
VOID
IrlapDiscoveryConf(PIRLMP_LINK_CB pIrlmpCb, IRDA_MSG *pMsg)
{
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: IRLAP_DISCOVERY_CONF\n")));
if (pIrlmpCb->LinkState != LINK_IN_DISCOVERY)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Link bad state\n")));
ASSERT(0);
return;// IRLMP_LINK_BAD_STATE;
}
pIrlmpCb->LinkState = LINK_DISCONNECTED;
if (pMsg->IRDA_MSG_DscvStatus == IRLAP_DISCOVERY_COMPLETED)
{
DEBUGMSG(ZONE_DSCV, (TEXT("IRLAP_DISCOVERY_CONF\r\n")));
UpdateDeviceList(pIrlmpCb->pIrdaLinkCb, pMsg->IRDA_MSG_pDevList);
}
// Initiate discovery on next link
IrdaEventSchedule(&EvDiscoveryReq, NULL);
// Initiate a connection if one was requested while in discovery
ScheduleConnectReq(pIrlmpCb);
}
/*****************************************************************************
*
* @func void | UpdateDeviceList | Determines if new devices need to be
* added or old ones removed from the device
* list maintained by IRLMP
*
* @parm LIST_ENTRY * | pDevList | pointer to a list of devices
*/
void
UpdateDeviceList(PIRDA_LINK_CB pIrdaLinkCb, LIST_ENTRY *pNewDevList)
{
IRDA_DEVICE *pNewDevice;
IRDA_DEVICE *pOldDevice;
IRDA_DEVICE *pDevice;
BOOLEAN DeviceInList;
DEBUGMSG(ZONE_DSCV, (TEXT("+UpdateDeviceList(0x%x, 0x%x)\r\n"),
pIrdaLinkCb, pNewDevList));
NdisAcquireSpinLock(&SpinLock);
// Add new devices, set not seen count to zero if devices is
// seen again
for (pNewDevice = (IRDA_D
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -