📄 irlap.c
字号:
// Update the device discovery info. IrLMP has already updated
// NickName & NickNameLen.
// Build the discovery info
Val = Hints;
DscvInfoLen = 0;
for (i = 0, Mask = 0xFF000000; i < 4; i++, Mask >>= 8)
{
if (Mask & Val || DscvInfoLen > 0)
{
DscvInfoBuf[DscvInfoLen++] = (UCHAR)
((Mask & Val) >> (8 * (3-i)));
}
}
DscvInfoBuf[DscvInfoLen++] = CharSet;
RtlCopyMemory(DscvInfoBuf+DscvInfoLen, NickName, NickNameLen);
DscvInfoLen += NickNameLen;
DscvInfoLen = DscvInfoLen > IRLAP_DSCV_INFO_LEN ?
IRLAP_DSCV_INFO_LEN : DscvInfoLen;
CTEMemCopy(pIrlapCb->LocalDevice.DscvInfo, DscvInfoBuf, DscvInfoLen);
pIrlapCb->LocalDevice.DscvInfoLen = DscvInfoLen;
IMsg.IRDA_MSG_Op = MAC_ACQUIRE_RESOURCES;
}
else
{
IMsg.IRDA_MSG_Op = MAC_RELEASE_RESOURCES;
}
IMsg.IRDA_MSG_pMacConfig = pMsg->IRDA_MSG_pLinkConfig;
IrmacDown(pMsg->IRDA_MSG_pLinkContext, &IMsg);
return (IMsg.IRDA_MSG_MacConfigStatus);
}
/*****************************************************************************
*
* ProcessDiscoveryReq - Process Discovery request from LMP
*
*/
UINT
ProcessDiscoveryReq(PIRLAP_CB pIrlapCb,
PIRDA_MSG pMsg)
{
IRDA_MSG IMsg;
switch (pIrlapCb->State)
{
case NDM:
if (pMsg->IRDA_MSG_SenseMedia == TRUE)
{
IMsg.Prim = MAC_CONTROL_REQ;
IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME;
IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
pIrlapCb->State = DSCV_MEDIA_SENSE;
IRLAP_LOG_ACTION((pIrlapCb,TEXT("MAC_CONTROL_REQ (mediasense)")));
}
else
{
pIrlapCb->SlotCnt = 0;
pIrlapCb->GenNewAddr = FALSE;
FreeDevList(&pIrlapCb->DevList);
SendDscvXIDCmd(pIrlapCb);
IMsg.Prim = MAC_CONTROL_REQ;
IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
IMsg.IRDA_MSG_SenseTime = DiscoverTimeout;
IRLAP_LOG_ACTION((pIrlapCb,TEXT("MAC_CONTROL_REQ (dscvsense)")));
IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
pIrlapCb->State = DSCV_QUERY;
}
break;
case DSCV_REPLY:
return IRLAP_REMOTE_DISCOVERY_IN_PROGRESS_ERR;
case SNRM_RECEIVED:
return IRLAP_REMOTE_CONNECTION_IN_PROGRESS_ERR;
case P_CLOSE:
pIrlapCb->DscvAfterClose = TRUE;
break;
default:
ASSERT(0);
return IRLAP_BAD_STATE;
}
return SUCCESS;
}
/*****************************************************************************
*
* ProcessDisconnectReq - Process disconnect request from LMP
*
*/
VOID
ProcessDisconnectReq(PIRLAP_CB pIrlapCb)
{
ReturnRxTxWinMsgs(pIrlapCb);
switch (pIrlapCb->State)
{
case NDM:
IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
break;
case SNRM_SENT:
IrlapTimerStop(TEXT("ProcessDisconnectResp: SNRM_SENT"), pIrlapCb, &pIrlapCb->FinalTimer);
case DSCV_MEDIA_SENSE:
case DSCV_QUERY:
case DSCV_REPLY:
case CONN_MEDIA_SENSE:
pIrlapCb->State = NDM;
break;
case BACKOFF_WAIT:
IrlapTimerStop(TEXT("ProcessDisconnectResp: BACKOFF_WAIT"), pIrlapCb, &pIrlapCb->BackoffTimer);
pIrlapCb->State = NDM;
break;
case SNRM_RECEIVED:
pIrlapCb->ConnAddr = pIrlapCb->SNRMConnAddr;
SendDM(pIrlapCb);
pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR;
pIrlapCb->State = NDM;
break;
case P_XMIT:
pIrlapCb->LocalDiscReq = TRUE;
IrlapTimerStop(TEXT("ProcessDisconnectResp: P_XMIT"), pIrlapCb, &pIrlapCb->PollTimer);
SendDISC(pIrlapCb);
IrlapTimerStart(TEXT("ProcessDisconnectResp: P_XMIT"), pIrlapCb, &pIrlapCb->FinalTimer);
pIrlapCb->RetryCnt = 0;
pIrlapCb->State = P_CLOSE;
break;
case P_RECV:
pIrlapCb->LocalDiscReq = TRUE;
pIrlapCb->State = P_DISCONNECT_PEND;
break;
case S_NRM:
pIrlapCb->LocalDiscReq = TRUE;
pIrlapCb->State = S_DISCONNECT_PEND;
break;
default:
ASSERT(0);
// return IRLAP_BAD_STATE;
}
}
/*****************************************************************************
*
* ProcessDataReq - Process data request from LMP
*
*/
UINT
ProcessDataAndUDataReq(PIRLAP_CB pIrlapCb,
PIRDA_MSG pMsg)
{
BOOLEAN LinkTurned;
int DataSize = (pMsg->IRDA_MSG_pHdrWrite - pMsg->IRDA_MSG_pHdrRead) +
(pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead);
UINT rc;
if (DataSize > pIrlapCb->RemoteDataSize)
{
rc = IRLAP_BAD_DATA_REQUEST;
goto pdaudr_fail;
}
switch (pIrlapCb->State)
{
case P_XMIT:
// Enque message, then drain the message list. If the link
// was turned in the process of draining messages stop Poll Timer,
// start Final Timer and enter P_RECV. Otherwise we'll stay in P_XMIT
// waiting for more data requests from LMP or Poll Timer expiration
EnqueMsgList(&pIrlapCb->TxMsgList, pMsg, -1);
XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned);
if (LinkTurned)
{
IrlapTimerStop(TEXT("ProcessDataAndUDataReq: P_XMIT"), pIrlapCb, &pIrlapCb->PollTimer);
IrlapTimerStart(TEXT("ProcessDataAndUDataReq: P_XMIT"), pIrlapCb, &pIrlapCb->FinalTimer);
pIrlapCb->State = P_RECV;
}
return SUCCESS;
case P_DISCONNECT_PEND: //For pending disc states, take the message.
case S_DISCONNECT_PEND: // They will be returned when the link discs
case P_RECV:
case S_NRM:
// Que the message for later transmission
IRLAP_LOG_ACTION((pIrlapCb, TEXT("Queueing request")));
EnqueMsgList(&pIrlapCb->TxMsgList, pMsg, -1);
return SUCCESS;
default:
if (pMsg->Prim == IRLAP_DATA_REQ)
{
ASSERT(0);
rc = IRLAP_BAD_STATE;
goto pdaudr_fail;
}
else
{
if (pIrlapCb->State == NDM)
{
SendUIFrame(pIrlapCb, pMsg);
}
else
{
IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
rc = SUCCESS;
goto pdaudr_fail;
}
}
}
return SUCCESS;
pdaudr_fail:
//
// Check if the msg should be freed
//
if ((NULL == pMsg->IRDA_MSG_pOwner) && (pMsg->IRDA_MSG_SegFlags & SEG_LOCAL)) {
FreeIrdaBuf(IrdaMsgPool, pMsg);
}
return rc;
}
/*****************************************************************************
*
*/
VOID
XmitTxMsgList(PIRLAP_CB pIrlapCb, BOOLEAN AlwaysTurnLink,
BOOLEAN *pLinkTurned)
{
IRDA_MSG *pMsg;
UINT LinkTurned;
LinkTurned = FALSE;
// If the remote is not busy send data
// If we need to clear the local busy condition, don't send data send RR
if (!pIrlapCb->RemoteBusy && !pIrlapCb->ClrLocalBusy)
{
while (!LinkTurned &&
(DequeMsgList(&pIrlapCb->TxMsgList, &pMsg) == SUCCESS))
{
pIrlapCb->FastPollCount = IRLAP_FAST_POLL_COUNT;
pIrlapCb->PollTimer.Timeout = IRLAP_FAST_POLL_TIME >
pIrlapCb->RemoteMaxTAT ? pIrlapCb->RemoteMaxTAT : IRLAP_FAST_POLL_TIME;
if (pMsg->Prim == IRLAP_DATA_REQ)
{
// Insert message into transmit window
pIrlapCb->TxWin.pMsg[pIrlapCb->Vs] = pMsg;
pMsg->IRDA_MSG_SendRefCnt = 1;
// Send message. If full window or there are no
// more data requests, send with PF Set (turns link).
if ((pIrlapCb->Vs == (pIrlapCb->TxWin.Start +
pIrlapCb->RemoteWinSize-1) % IRLAP_MOD) ||
(0 == pIrlapCb->TxMsgList.Len /*AlwaysTurnLink*/))
{
SendIFrame(pIrlapCb,
pMsg,
pIrlapCb->Vs,
IRLAP_PFBIT_SET);
LinkTurned = TRUE;
}
else
{
SendIFrame(pIrlapCb,
pMsg,
pIrlapCb->Vs,
IRLAP_PFBIT_CLEAR);
}
pIrlapCb->Vs = (pIrlapCb->Vs + 1) % IRLAP_MOD;
}
else // IRLAP_UDATA_REQUEST
{
// For now, always turn link
SendUIFrame(pIrlapCb, pMsg);
pMsg->Prim = IRLAP_UDATA_CONF;
pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_COMPLETED;
IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
LinkTurned = TRUE;
}
}
pIrlapCb->TxWin.End = pIrlapCb->Vs;
}
if ((AlwaysTurnLink && !LinkTurned) || pIrlapCb->ClrLocalBusy)
{
SendRR_RNR(pIrlapCb);
LinkTurned = TRUE;
if (pIrlapCb->ClrLocalBusy)
{
pIrlapCb->ClrLocalBusy = FALSE;
}
}
if (pLinkTurned != NULL)
{
*pLinkTurned = LinkTurned;
}
}
VOID
GotoPCloseState(PIRLAP_CB pIrlapCb)
{
IRDA_MSG IMsg;
if (!pIrlapCb->LocalDiscReq)
{
IMsg.Prim = IRLAP_DISCONNECT_IND;
IMsg.IRDA_MSG_DiscStatus = IRLAP_REMOTE_INITIATED;
IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
}
ReturnRxTxWinMsgs(pIrlapCb);
pIrlapCb->State = P_CLOSE;
}
VOID
GotoNDMThenDscvOrConn(PIRLAP_CB pIrlapCb)
{
IRDA_MSG IMsg;
if (pIrlapCb->ConnAfterClose)
{
pIrlapCb->ConnAfterClose = FALSE;
IMsg.Prim = MAC_CONTROL_REQ;
IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME;
IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
pIrlapCb->State = CONN_MEDIA_SENSE;
IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (media sense)")));
return;
}
if (pIrlapCb->DscvAfterClose)
{
pIrlapCb->DscvAfterClose = FALSE;
IMsg.Prim = MAC_CONTROL_REQ;
IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME;
IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
pIrlapCb->State = DSCV_MEDIA_SENSE;
IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (media sense)")));
return;
}
pIrlapCb->State = NDM;
return;
}
/*****************************************************************************
*
* ProcessMACControlConf - Process a control confirm from MAC
*
*/
VOID
ProcessMACControlConf(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg)
{
IRDA_MSG IMsg;
if (pMsg->IRDA_MSG_Op != MAC_MEDIA_SENSE)
{
ASSERT(0);
return; //IRLAP_BAD_OP;
}
switch (pIrlapCb->State)
{
case DSCV_MEDIA_SENSE:
switch (pMsg->IRDA_MSG_OpStatus)
{
case MAC_MEDIA_CLEAR:
//IndicateLinkStatus(pIrlapCb, LINK_STATUS_DISCOVERING);
pIrlapCb->SlotCnt = 0;
pIrlapCb->GenNewAddr = FALSE;
FreeDevList(&pIrlapCb->DevList);
SendDscvXIDCmd(pIrlapCb);
IMsg.Prim = MAC_CONTROL_REQ;
IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
IMsg.IRDA_MSG_SenseTime = DiscoverTimeout;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -