📄 irlap.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.
//
/*****************************************************************************
*
*
* @doc
* @module irlap.c | Provides IrLAP API
*
* Date: 4/15/95
*
* @comm
*
* This module exports the following API's:
*
* IrlapDown(Message)
* Receives from LMP:
* - Discovery request
* - Connect request/response
* - Disconnect request
* - Data/UData request
*
* IrlapUp(Message)
* Receives from MAC:
* - Data indications
* - Control confirmations
*
* IrlapTimerExp(Timer)
* Receives from timer thread timer expiration notifications
*
* IrlapCloseLink()
* Shut down IRLAP and IRMAC.
*
* IrlapGetQosParmVal()
* Allows IRLMP to decode Qos.
*
* |---------|
* | IRLMP |
* |---------|
* /|\ |
* | |
* IrlmpUp() | | IrlapDown()
* | |
* | \|/
* |---------| IRDA_TimerStart/Stop() |-------|
* | |-------------------------->| |
* | IRLAP | | TIMER |
* | |<--------------------------| |
* |---------| XTimerExp() |-------|
* /|\ |
* | |
* IrlapUp() | |IrmacDown()
* | |
* | \|/
* |---------|
* | IRMAC |
* |---------|
*
*
* Discovery Request
*
* |-------| IRLAP_DISCOVERY_REQ |-------|
* | |---------------------------------------------------->| |
* | IRLMP | | IRLAP |
* | |<----------------------------------------------------| |
* |-------| IRLAP_DISCOVERY_CONF |-------|
* DscvStatus = IRLAP_DISCOVERY_COMPLETE
* IRLAP_DISCOVERY_COLLISION
* MAC_MEDIA_BUSY
*
* Connect Request
*
* |-------| IRLAP_CONNECT_REQ |-------|
* | |---------------------------------------------------->| |
* | IRLMP | | IRLAP |
* | |<----------------------------------------------------| |
* |-------| IRLAP_CONNECT_CONF |-------|
* ConnStatus = IRLAP_CONNECTION_COMPLETE
* IRLAP_DISCONNECT_IND
* DiscStatus = IRLAP_NO_RESPONSE
* MAC_MEDIA_BUSY
*
* Disconnect Request
*
* |-------| IRLAP_DISCONNECT_REQ |-------|
* | |---------------------------------------------------->| |
* | IRLMP | | IRLAP |
* | |<----------------------------------------------------| |
* |-------| IRLAP_DISCONNECT_IND |-------|
* DiscStatus = IRLAP_DISCONNECT_COMPLETE
* IRLAP_NO_RESPONSE
*
* UData/Data Request
*
* |-------| IRLAP_DATA/UDATA_REQ |-------|
* | |---------------------------------------------------->| |
* | IRLMP | | IRLAP |
* | |<----------------------------------------------------| |
* |-------| IRLAP_DATA_CONF |-------|
* DataStatus = IRLAP_DATA_REQUEST_COMPLETED
* IRLAP_DATA_REQUEST_FAILED_LINK_RESET
*
* See irda.h for complete message definitions
*/
#include <irda.h>
#ifdef UNDER_CE
#include <linklist.h>
// defined in NT irioctl.h
#define LINK_STATUS_IDLE 0
#define LINK_STATUS_DISCOVERING 1
#define LINK_STATUS_CONNECTED 2
#define LINK_STATUS_INTERRUPTED 3
#else // UNDER_CE
#include <irioctl.h>
#endif // !UNDER_CE
#include <irlap.h>
#include <irlmp.h>
#include <irlapp.h>
#include <irlapio.h>
#include <irlaplog.h>
// In IrNDIS.c.
extern UINT SlotTimeout;
extern UINT DiscoverTimeout;
#ifdef TEMPERAMENTAL_SERIAL_DRIVER
int TossedDups;
#endif
UINT IrlapSlotTable[] = {1, 6, 8, 16};
UCHAR IrlapBroadcastDevAddr[IRDA_DEV_ADDR_LEN] = {0xFF,0xFF,0xFF,0xFF};
// Parameter Value (PV) tables used for negotation
// bit0 1 2 3 4
// 5 6 7 8
// --------------------------------------------
UINT vBaudTable[] = {2400, 9600, 19200, 38400, 57600,\
115200, 576000, 1152000, 4000000,16000000};
UINT vMaxTATTable[] = {500, 250, 100, 50, 25, \
10, 5, 0, 0, 0 };
UINT vMinTATTable[] = {10000, 5000, 1000, 500, 100, \
50, 10, 0, 0, 0 };
UINT vDataSizeTable[] = {64, 128, 256, 512, 1024, \
2048, 0, 0, 0, 0 };
UINT vWinSizeTable[] = {1, 2, 3, 4, 5, \
6, 7, 0, 0, 0 };
UINT vBOFSTable[] = {48, 24, 12, 5, 3, \
2, 1, 0, 0, 0 };
UINT vDiscTable[] = {3, 8, 12, 16, 20, \
25, 30, 40, 0, 0 };
UINT vThreshTable[] = {0, 3, 3, 3, 3, \
3, 3, 3, 0, 0 };
UINT vBOFSDivTable[] = {48, 12, 6, 3, 2, \
1, 1, 1, 1, 1 };
// Tables for determining maximum line capacity for baud, max turn time
// max turn time - 500ms 250ms 100ms 50ms 25ms 10ms 5ms
// -------------------------------------------------------------
UINT MAXCAP_9600[] = {400, 200, 80, 0, 0, 0, 0, 0, 0, 0};
UINT MAXCAP_19200[] = {800, 400, 160, 0, 0, 0, 0, 0, 0, 0};
UINT MAXCAP_38400[] = {1600, 800, 320, 0, 0, 0, 0, 0, 0, 0};
UINT MAXCAP_57600[] = {2360, 1180, 472, 0, 0, 0, 0, 0, 0, 0};
UINT MAXCAP_115200[] = {4800, 2400, 960, 480, 240, 96, 48, 24, 12, 6};
UINT MAXCAP_576000[] = {28800, 11520, 5760, 2880, 1440, 720, 360, 180, 90, 45};
UINT MAXCAP_1152000[] = {57600, 28800, 11520, 5760, 2880, 1440, 720, 360, 180, 90};
UINT MAXCAP_4000000[] = {200000, 100000, 40000, 20000, 10000, 5000, 2500, 1200, 600, 300};
UINT MAXCAP_16000000[] ={800000, 400000, 160000, 80000, 40000, 20000, 10000, 5000, 2500, 1200};
// prototypes
STATIC VOID InitializeState(PIRLAP_CB, IRLAP_STN_TYPE);
STATIC VOID ReturnRxTxWinMsgs(PIRLAP_CB);
STATIC UINT ProcessLinkControlReq(PIRLAP_CB, PIRDA_MSG);
STATIC UINT ProcessConnectReq(PIRLAP_CB, PIRDA_MSG);
STATIC VOID ProcessConnectResp(PIRLAP_CB, PIRDA_MSG);
STATIC UINT ProcessDiscoveryReq(PIRLAP_CB, PIRDA_MSG);
STATIC VOID ProcessDisconnectReq(PIRLAP_CB);
STATIC UINT ProcessDataAndUDataReq(PIRLAP_CB, PIRDA_MSG);
STATIC VOID XmitTxMsgList(PIRLAP_CB, BOOLEAN, BOOLEAN *);
STATIC VOID GotoPCloseState(PIRLAP_CB);
STATIC VOID GotoNDMThenDscvOrConn(PIRLAP_CB);
STATIC VOID ProcessMACControlConf(PIRLAP_CB, PIRDA_MSG);
STATIC VOID ProcessMACDataInd(PIRLAP_CB, PIRDA_MSG , BOOLEAN *);
STATIC VOID ProcessDscvXIDCmd(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
STATIC VOID ProcessDscvXIDRsp(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
STATIC VOID ExtractQosParms(IRDA_QOS_PARMS *, UCHAR *, UCHAR *);
STATIC VOID InitDscvCmdProcessing(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *);
STATIC VOID ExtractDeviceInfo(IRDA_DEVICE *, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
STATIC BOOLEAN DevInDevList(UCHAR[], LIST_ENTRY *);
STATIC VOID AddDevToList(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
STATIC VOID FreeDevList(LIST_ENTRY *);
STATIC VOID ProcessSNRM(PIRLAP_CB, IRLAP_SNRM_FORMAT *, UCHAR *);
STATIC VOID ProcessUA(PIRLAP_CB, IRLAP_UA_FORMAT *, UCHAR *);
STATIC VOID ProcessDISC(PIRLAP_CB);
STATIC VOID ProcessRD(PIRLAP_CB);
STATIC VOID ProcessRNRM(PIRLAP_CB);
STATIC VOID ProcessDM(PIRLAP_CB);
STATIC VOID ProcessFRMR(PIRLAP_CB);
STATIC VOID ProcessTEST(PIRLAP_CB, PIRDA_MSG, IRLAP_UA_FORMAT *, int, int);
STATIC VOID ProcessUI(PIRLAP_CB, PIRDA_MSG, int, int);
STATIC VOID ProcessREJ_SREJ(PIRLAP_CB, int, PIRDA_MSG, int, int, UINT);
STATIC VOID ProcessRR_RNR(PIRLAP_CB, int, PIRDA_MSG, int, int, UINT);
STATIC VOID ProcessIFrame(PIRLAP_CB, PIRDA_MSG, int, int, UINT, UINT, BOOLEAN *);
STATIC BOOLEAN InvalidNs(PIRLAP_CB, UINT);
STATIC BOOLEAN InvalidNr(PIRLAP_CB, UINT);
STATIC BOOLEAN InWindow(UINT, UINT, UINT);
STATIC VOID ProcessInvalidNsOrNr(PIRLAP_CB, int);
STATIC VOID ProcessInvalidNr(PIRLAP_CB, int);
STATIC VOID InsertRxWinAndForward(PIRLAP_CB, PIRDA_MSG, UINT, BOOLEAN *);
STATIC VOID ResendRejects(PIRLAP_CB, UINT);
STATIC VOID ConfirmAckedTxMsgs(PIRLAP_CB, UINT);
STATIC VOID MissingRxFrames(PIRLAP_CB);
STATIC VOID IFrameOtherStates(PIRLAP_CB, int, int);
STATIC UINT NegotiateQosParms(PIRLAP_CB, IRDA_QOS_PARMS *);
STATIC VOID ApplyQosParms(PIRLAP_CB);
STATIC VOID StationConflict(PIRLAP_CB);
STATIC VOID ApplyDefaultParms(PIRLAP_CB);
STATIC VOID ResendDISC(PIRLAP_CB);
STATIC BOOLEAN IgnoreState(PIRLAP_CB);
STATIC BOOLEAN MyDevAddr(PIRLAP_CB, UCHAR []);
STATIC VOID SlotTimerExp(PVOID);
STATIC VOID FinalTimerExp(PVOID);
STATIC VOID PollTimerExp(PVOID);
STATIC VOID BackoffTimerExp(PVOID);
STATIC VOID WDogTimerExp(PVOID);
STATIC VOID QueryTimerExp(PVOID);
#if DBG
void _inline IrlapTimerStart(
TCHAR *lpszFunc,
PIRLAP_CB pIrlapCb,
PIRDA_TIMER pTmr)
{
IRLAP_LOG_ACTION((pIrlapCb, TEXT("Start %hs timer for %dms"), pTmr->pName,
pTmr->Timeout));
DEBUGMSG(DBG_TIMER,
(TEXT("%hs timer started @ %d (%s)\r\n"),
pTmr->pName,
GetTickCount(),
lpszFunc));
IrdaTimerStart(pTmr);
}
void _inline IrlapTimerStop(
TCHAR *lpszFunc,
PIRLAP_CB pIrlapCb,
PIRDA_TIMER pTmr)
{
IRLAP_LOG_ACTION((pIrlapCb, TEXT("Stop %hs timer"), pTmr->pName));
IrdaTimerStop(pTmr);
DEBUGMSG(DBG_TIMER,
(TEXT("%hs timer stop @ %d (%s) - %hs\r\n"),
pTmr->pName,
GetTickCount(),
lpszFunc,
pTmr->Late ? "LATE" : "not late"));
}
#else
#define IrlapTimerStart(f,c,t) IrdaTimerStart(t)
#define IrlapTimerStop(f,c,t) IrdaTimerStop(t)
#endif
VOID
IrlapOpenLink(OUT PNTSTATUS Status,
IN PIRDA_LINK_CB pIrdaLinkCb,
IN IRDA_QOS_PARMS *pQos,
IN UCHAR *pDscvInfo,
IN int DscvInfoLen,
IN UINT MaxSlot,
IN UCHAR *pDeviceName,
IN int DeviceNameLen,
IN UCHAR CharSet)
{
UINT rc = SUCCESS;
int i;
IRDA_MSG IMsg;
PIRLAP_CB pIrlapCb;
NDIS_STRING AStr = NDIS_STRING_CONST("InfraredTransceiverType");
DEBUGMSG(DBG_IRLAP, (TEXT("IrlapOpenLink\n")));
if (IRDA_ALLOC_MEM(pIrlapCb, sizeof(IRLAP_CB), MT_IRLAPCB) == NULL)
{
DEBUGMSG(DBG_ERROR, (TEXT("Alloc failed\n")));
*Status = STATUS_INSUFFICIENT_RESOURCES;
return;
}
IrlmpOpenLink(Status,
pIrdaLinkCb,
pDeviceName,
DeviceNameLen,
CharSet);
if (*Status != STATUS_SUCCESS)
{
DEBUGMSG(DBG_ERROR, (TEXT("IrlmpOpenLink failed\n")));
IRDA_FREE_MEM(pIrlapCb);
return;
}
pIrdaLinkCb->IrlapContext = pIrlapCb;
DscvInfoLen = DscvInfoLen > IRLAP_DSCV_INFO_LEN ?
IRLAP_DSCV_INFO_LEN : DscvInfoLen;
CTEMemCopy(pIrlapCb->LocalDevice.DscvInfo, pDscvInfo, DscvInfoLen);
pIrlapCb->LocalDevice.DscvInfoLen = DscvInfoLen;
CTEMemCopy(&pIrlapCb->LocalQos, pQos, sizeof(IRDA_QOS_PARMS));
pIrlapCb->MaxSlot = MaxSlot;
pIrlapCb->pIrdaLinkCb = pIrdaLinkCb;
InitMsgList(&pIrlapCb->TxMsgList);
InitializeListHead(&pIrlapCb->DevList);
for (i = 0; i < IRLAP_MOD; i++)
{
pIrlapCb->TxWin.pMsg[i] = NULL;
pIrlapCb->RxWin.pMsg[i] = NULL;
}
// Get the local MAX TAT (for final timeout)
if ((pIrlapCb->LocalMaxTAT =
IrlapGetQosParmVal(vMaxTATTable,
pIrlapCb->LocalQos.bfMaxTurnTime, NULL)) == -1)
{
*Status = STATUS_UNSUCCESSFUL;
return /*IRLAP_BAD_QOS*/;
}
if ((pIrlapCb->LocalWinSize =
IrlapGetQosParmVal(vWinSizeTable,
pIrlapCb->LocalQos.bfWindowSize, NULL)) == -1)
{
*Status = STATUS_UNSUCCESSFUL;
return /*IRLAP_BAD_QOS*/;
}
// initialize as PRIMARY so UI frames in contention
// state sends CRBit = cmd
InitializeState(pIrlapCb, PRIMARY);
pIrlapCb->State = NDM;
// Generate random local address
StoreULAddr(pIrlapCb->LocalDevice.DevAddr, (ULONG) GetMyDevAddr(FALSE));
pIrlapCb->LocalDevice.IRLAP_Version = 0;
pIrlapCb->Baud = IRLAP_CONTENTION_BAUD;
pIrlapCb->RemoteMaxTAT = IRLAP_CONTENTION_MAX_TAT;
pIrlapCb->RemoteDataSize = IRLAP_CONTENTION_DATA_SIZE;
pIrlapCb->RemoteWinSize = IRLAP_CONTENTION_WIN_SIZE;
pIrlapCb->RemoteNumBOFS = IRLAP_CONTENTION_BOFS;
pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR;
pIrlapCb->N1 = 0; // calculated at negotiation
pIrlapCb->N2 = 0;
pIrlapCb->N3 = 5; // recalculated after negotiation ??
#if DBG
pIrlapCb->PollTimer.pName = "Poll";
pIrlapCb->FinalTimer.pName = "Final" ;
pIrlapCb->SlotTimer.pName = "Slot";
pIrlapCb->QueryTimer.pName = "Query";
pIrlapCb->WDogTimer.pName = "WatchDog";
pIrlapCb->BackoffTimer.pName = "Backoff";
#endif
IrdaTimerInitialize(&pIrlapCb->PollTimer,
PollTimerExp,
pIrlapCb->RemoteMaxTAT,
pIrlapCb,
pIrdaLinkCb);
IrdaTimerInitialize(&pIrlapCb->FinalTimer,
FinalTimerExp,
pIrlapCb->LocalMaxTAT,
pIrlapCb,
pIrdaLinkCb);
IrdaTimerInitialize(&pIrlapCb->SlotTimer,
SlotTimerExp,
SlotTimeout,
pIrlapCb,
pIrdaLinkCb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -