From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/tdi/irda/dirs | 10 + private/ntos/tdi/irda/driver/irda.c | 132 + private/ntos/tdi/irda/driver/irndis.c | 706 +++++ private/ntos/tdi/irda/driver/makefile | 7 + private/ntos/tdi/irda/driver/sources | 15 + private/ntos/tdi/irda/inc/af_irda.h | 100 + private/ntos/tdi/irda/inc/decdirda.h | 174 ++ private/ntos/tdi/irda/inc/irda.h | 857 ++++++ private/ntos/tdi/irda/inc/irdalink.h | 34 + private/ntos/tdi/irda/inc/irerr.h | 110 + private/ntos/tdi/irda/inc/irlap.h | 66 + private/ntos/tdi/irda/inc/irlaplog.h | 44 + private/ntos/tdi/irda/inc/irlmp.h | 60 + private/ntos/tdi/irda/inc/irmac.h | 32 + private/ntos/tdi/irda/inc/oscfg.h | 62 + private/ntos/tdi/irda/inc/tmp.h | 31 + private/ntos/tdi/irda/irlap/irlap.c | 4519 ++++++++++++++++++++++++++++++++ private/ntos/tdi/irda/irlap/irlapio.c | 900 +++++++ private/ntos/tdi/irda/irlap/irlapio.h | 32 + private/ntos/tdi/irda/irlap/irlaplog.c | 265 ++ private/ntos/tdi/irda/irlap/irlapp.h | 299 +++ private/ntos/tdi/irda/irlap/makefile | 6 + private/ntos/tdi/irda/irlap/sources | 23 + 23 files changed, 8484 insertions(+) create mode 100644 private/ntos/tdi/irda/dirs create mode 100644 private/ntos/tdi/irda/driver/irda.c create mode 100644 private/ntos/tdi/irda/driver/irndis.c create mode 100644 private/ntos/tdi/irda/driver/makefile create mode 100644 private/ntos/tdi/irda/driver/sources create mode 100644 private/ntos/tdi/irda/inc/af_irda.h create mode 100644 private/ntos/tdi/irda/inc/decdirda.h create mode 100644 private/ntos/tdi/irda/inc/irda.h create mode 100644 private/ntos/tdi/irda/inc/irdalink.h create mode 100644 private/ntos/tdi/irda/inc/irerr.h create mode 100644 private/ntos/tdi/irda/inc/irlap.h create mode 100644 private/ntos/tdi/irda/inc/irlaplog.h create mode 100644 private/ntos/tdi/irda/inc/irlmp.h create mode 100644 private/ntos/tdi/irda/inc/irmac.h create mode 100644 private/ntos/tdi/irda/inc/oscfg.h create mode 100644 private/ntos/tdi/irda/inc/tmp.h create mode 100644 private/ntos/tdi/irda/irlap/irlap.c create mode 100644 private/ntos/tdi/irda/irlap/irlapio.c create mode 100644 private/ntos/tdi/irda/irlap/irlapio.h create mode 100644 private/ntos/tdi/irda/irlap/irlaplog.c create mode 100644 private/ntos/tdi/irda/irlap/irlapp.h create mode 100644 private/ntos/tdi/irda/irlap/makefile create mode 100644 private/ntos/tdi/irda/irlap/sources (limited to 'private/ntos/tdi/irda') diff --git a/private/ntos/tdi/irda/dirs b/private/ntos/tdi/irda/dirs new file mode 100644 index 000000000..0ea6a777b --- /dev/null +++ b/private/ntos/tdi/irda/dirs @@ -0,0 +1,10 @@ +DIRS= irlap \ + driver + + + + + + + + diff --git a/private/ntos/tdi/irda/driver/irda.c b/private/ntos/tdi/irda/driver/irda.c new file mode 100644 index 000000000..72bdf3881 --- /dev/null +++ b/private/ntos/tdi/irda/driver/irda.c @@ -0,0 +1,132 @@ +/* + * IRDA.C + * + * + * + * + * + * + * + * + * + * + */ + + +//#include +#include +#include +#include +#include +#include +#include + +int irdaDbgSettings = 1 + \ + DBG_ERROR + \ + DBG_WARN + \ +/*DBG_FUNCTION + */ \ + /*DBG_NDIS +*/ \ +/* DBG_IRLAPLOG +*/ \ + DBG_IRLAP; + +LIST_ENTRY IrdaLinkCbList; + +/* + ******************************************************************************** + * DriverEntry + ******************************************************************************** + * + * + * + */ +NTSTATUS DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + + NTSTATUS Status = STATUS_SUCCESS; + + DEBUGMSG(DBG_FUNCTION,("+DriverEntry(IRDA)\n")); + + InitializeListHead(&IrdaLinkCbList); + + // IRLMP initialize + // IRLAP initialize + + if ((Status = IrdaNdisInitialize()) != STATUS_SUCCESS) + { + goto done; + } + +done: + + DEBUGMSG(DBG_FUNCTION, ("-DriverEntry(IRDA), rc %x\n", Status)); + + return Status; +} + +void +IrdaTimerInitialize(PIRDA_TIMER pTimer, + VOID (*ExpFunc)(PVOID Context), + UINT Timeout, + PVOID Context) +{ + CTEInitTimer(&pTimer->CteTimer); + pTimer->ExpFunc = ExpFunc; + pTimer->Context = Context; + pTimer->Timeout = Timeout; + + DEBUGMSG(DBG_FUNCTION, ("IrdaTimerIntialize %s\n", pTimer->pName)); +} + +void +TimerFunc(CTEEvent *Event, void *Arg) +{ + PIRDA_TIMER pIrdaTimer = (PIRDA_TIMER) Arg; + int rc; + + DEBUGMSG(DBG_FUNCTION, ("Timer expired, context %x\n", + pIrdaTimer)); + + if (pIrdaTimer->Late != TRUE) + { + pIrdaTimer->ExpFunc(pIrdaTimer->Context); + } + else + { + DEBUGMSG(DBG_WARN, + (TEXT("IRDA TIMER LATE, ignoring\r\n"))); + + pIrdaTimer->Late = FALSE; + } + + return; +} + +VOID +IrdaTimerStart(PIRDA_TIMER pIrdaTimer) +{ + + pIrdaTimer->Late = FALSE; + CTEStartTimer(&pIrdaTimer->CteTimer, pIrdaTimer->Timeout, + TimerFunc, (PVOID) pIrdaTimer); + + DEBUGMSG(DBG_FUNCTION, ("Start timer %s (%dms) context %x\n", + pIrdaTimer->pName, + pIrdaTimer->Timeout, + pIrdaTimer)); + return; +} + +VOID +IrdaTimerStop(PIRDA_TIMER pIrdaTimer) +{ + if (CTEStopTimer(&pIrdaTimer->CteTimer) == 0) + { + pIrdaTimer->Late = TRUE; + } + DEBUGMSG(DBG_FUNCTION, ("Timer %s stopped\n", pIrdaTimer->pName)); + + return; +} + diff --git a/private/ntos/tdi/irda/driver/irndis.c b/private/ntos/tdi/irda/driver/irndis.c new file mode 100644 index 000000000..903e53570 --- /dev/null +++ b/private/ntos/tdi/irda/driver/irndis.c @@ -0,0 +1,706 @@ +/* + * + * + * + * + * + * + * + * + * + * + * + */ + + +//#include +#include +#include +#include +#include +#include + +NDIS_HANDLE NdisIrdaHandle = NULL; + +// Translate an OID query to LAP definition +VOID +OidToLapQos( + UINT ParmTable[], + UINT ValArray[], + UINT Cnt, + PUINT pBitField) +{ + UINT i, j; + + *pBitField = 0; + for (i = 0; i < Cnt; i++) + for (j = 0; j <= PV_TABLE_MAX_BIT; j++) + if (ValArray[i] == ParmTable[j]) + *pBitField |= 1<SyncEvent); + + NdisRequest.RequestType = NdisRequestQueryInformation; + NdisRequest.DATA.QUERY_INFORMATION.Oid = Oid; + NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = pQBuf; + NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = + *pQBufLen * sizeof(UINT); + + NdisRequest(&Status, pIrdaLinkCb->NdisBindingHandle, &NdisRequest); + + if (Status == NDIS_STATUS_PENDING) + { + NdisWaitEvent(&pIrdaLinkCb->SyncEvent, 0); + Status = pIrdaLinkCb->SyncStatus; + } + + *pQBufLen = NdisRequest.DATA.QUERY_INFORMATION.BytesWritten / sizeof(UINT); + + return Status; +} + +// Sync request to set an Oid +NDIS_STATUS +IrdaSetOid( + IN PIRDA_LINK_CB pIrdaLinkCb, + IN NDIS_OID Oid, + IN UINT Val) +{ + NDIS_REQUEST NdisRequest; + NDIS_STATUS Status; + + NdisResetEvent(&pIrdaLinkCb->SyncEvent); + + NdisRequest.RequestType = NdisRequestSetInformation; + NdisRequest.DATA.SET_INFORMATION.Oid = Oid; + NdisRequest.DATA.SET_INFORMATION.InformationBuffer = &Val; + NdisRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof(UINT); + + NdisRequest(&Status, pIrdaLinkCb->NdisBindingHandle, &NdisRequest); + + if (Status == NDIS_STATUS_PENDING) + { + NdisWaitEvent(&pIrdaLinkCb->SyncEvent, 0); + Status = pIrdaLinkCb->SyncStatus; + } + return Status; +} + +// Allocate a message for LAP to use for internally generated frames. +IRDA_MSG * +AllocMacIMsg(PIRDA_LINK_CB pIrdaLinkCb) +{ + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + IRDA_MSG *pIMsg; + + pIMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList( + &pIrdaLinkCb->IMsgList, &pIrdaLinkCb->SpinLock); + + if (pIMsg == NULL) + { + NdisAllocateMemory(&pIMsg, sizeof(IRDA_MSG) + IRDA_MSG_DATA_SIZE, + 0, pa); + if (pIMsg == NULL) + return NULL; + pIrdaLinkCb->IMsgListLen++; + } + + // Indicate driver owns message + pIMsg->IRDA_MSG_pOwner = &pIrdaLinkCb->IMsgList; + + // Setup the pointers + pIMsg->IRDA_MSG_pHdrWrite = \ + pIMsg->IRDA_MSG_pHdrRead = pIMsg->IRDA_MSG_Header + IRDA_HEADER_LEN; + pIMsg->IRDA_MSG_pBase = \ + pIMsg->IRDA_MSG_pRead = \ + pIMsg->IRDA_MSG_pWrite = (BYTE *) pIMsg + sizeof(IRDA_MSG); + pIMsg->IRDA_MSG_pLimit = pIMsg->IRDA_MSG_pBase + IRDA_MSG_DATA_SIZE-1; + + return pIMsg; +} + +void IrdaRequestComplete( + IN NDIS_HANDLE IrdaBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ) +{ + PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext; + + DEBUGMSG(DBG_NDIS, ("+IrdaRequestComplete()\n")); + + pIrdaLinkCb->SyncStatus = Status; + NdisSetEvent(&pIrdaLinkCb->SyncEvent); + + return; +} + +VOID IrdaOpenAdapterComplete( + IN NDIS_HANDLE IrdaBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus + ) +{ + PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext; + + DEBUGMSG(DBG_NDIS, ("+IrdaOpenAdapterComplete() IrdaBindingContext %x, Status %x\n", + IrdaBindingContext, Status)); + + pIrdaLinkCb->SyncStatus = Status; + NdisSetEvent(&pIrdaLinkCb->SyncEvent); + + DEBUGMSG(DBG_NDIS, ("-IrdaOpenAdapterComplete()\n")); + + return; +} + +VOID IrdaCloseAdapterComplete( + IN NDIS_HANDLE IrdaBindingContext, + IN NDIS_STATUS Status + ) +{ + PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext; + + DEBUGMSG(DBG_NDIS, ("+IrdaCloseAdapterComplete()\n")); + + pIrdaLinkCb->SyncStatus = Status; + NdisSetEvent(&pIrdaLinkCb->SyncEvent); + + DEBUGMSG(DBG_NDIS, ("-IrdaCloseAdapterComplete()\n")); + + return; +} + +VOID IrdaSendComplete( + IN NDIS_HANDLE Context, + IN PNDIS_PACKET NdisPacket, + IN NDIS_STATUS Status + ) +{ + PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) Context; + PIRDA_PROTOCOL_RESERVED ProtocolReserved = \ + (PIRDA_PROTOCOL_RESERVED) NdisPacket->ProtocolReserved; + PIRDA_MSG pIMsg = ProtocolReserved->pIMsg; + PNDIS_BUFFER NdisBuffer; + + if (pIMsg->IRDA_MSG_pOwner == &pIrdaLinkCb->IMsgList) + { + NdisInterlockedInsertTailList(&pIrdaLinkCb->IMsgList, + &pIMsg->Linkage, + &pIrdaLinkCb->SpinLock); + } + + if (NdisPacket){ + NdisUnchainBufferAtFront(NdisPacket, &NdisBuffer); + while (NdisBuffer){ + NdisFreeBuffer(NdisBuffer); + NdisUnchainBufferAtFront(NdisPacket, &NdisBuffer); + } + + NdisFreePacket(NdisPacket); + } + + DEBUGMSG(DBG_NDIS, ("+IrdaSendComplete()\n")); + return; +} + +VOID IrdaTransferDataComplete( + IN NDIS_HANDLE IrdaBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ) +{ + DEBUGMSG(DBG_NDIS, ("+IrdaTransferDataComplete()\n")); + return; +} + +void IrdaResetComplete( + IN NDIS_HANDLE IrdaBindingContext, + IN NDIS_STATUS Status + ) +{ + DEBUGMSG(DBG_NDIS, ("+IrdaResetComplete()\n")); + return; +} + +NDIS_STATUS IrdaReceive( + IN NDIS_HANDLE IrdaBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookAheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ) +{ + DEBUGMSG(DBG_NDIS, ("+IrdaReceive()\n")); + + return NDIS_STATUS_SUCCESS; +} + +VOID IrdaReceiveComplete( + IN NDIS_HANDLE IrdaBindingContext + ) +{ + DEBUGMSG(DBG_NDIS, ("+IrdaReceiveComplete()\n")); + + return; +} + +VOID IrdaStatus( + IN NDIS_HANDLE IrdaBindingContext, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize + ) +{ + PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext; + + if (GeneralStatus == NDIS_STATUS_MEDIA_BUSY) + { + DEBUGMSG(DBG_NDIS, ("STATUS_MEDIA_BUSY\n")); + } +#ifdef DEBUG + else + { + DEBUGMSG(DBG_NDIS, ("Unknown Status indication\n")); + } +#endif + + return; +} + +VOID IrdaStatusComplete( + IN NDIS_HANDLE IrdaBindingContext + ) +{ + DEBUGMSG(DBG_NDIS, ("IrdaStatusComplete()\n")); + + return; +} + +INT IrdaReceivePacket( + IN NDIS_HANDLE IrdaBindingContext, + IN PNDIS_PACKET Packet + ) +{ + UINT BufCnt, TotalLen, BufLen; + PNDIS_BUFFER pNdisBuf; + IRDA_MSG IMsg; + BYTE *pData; + PIRDA_LINK_CB pIrdaLinkCb = IrdaBindingContext; + + DEBUGMSG(DBG_NDIS, ("+IrdaReceivePacket(%x)\n", pIrdaLinkCb)); + + NdisQueryPacket(Packet, NULL, &BufCnt, &pNdisBuf, &TotalLen); + + DEBUGMSG(DBG_NDIS, (" BufCnt %d, TotalLen %d\n", BufCnt, TotalLen)); + + NdisQueryBuffer(pNdisBuf, &pData, &BufLen); + + IMsg.Prim = MAC_DATA_IND; + IMsg.IRDA_MSG_pRead = pData; + IMsg.IRDA_MSG_pWrite = pData + BufLen; + + IrlapUp(pIrdaLinkCb->IrlapContext, &IMsg); + + return 0; +} + +VOID IrdaBindAdapter( + OUT PNDIS_STATUS pStatus, + IN NDIS_HANDLE BindContext, + IN PNDIS_STRING AdapterName, + IN PVOID SystemSpecific1, + IN PVOID SystemSpecific2 + ) +{ + NDIS_STATUS OpenErrorStatus; + NDIS_MEDIUM MediumArray[] = {NdisMediumIrda}; + UINT SelectedMediumIndex; + PIRDA_LINK_CB pIrdaLinkCb; + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + UINT UintArray[8]; + UINT UintArrayCnt; + IRDA_MSG *pIMsg; + // ******************************************************* + // ******************************************************* + // TEMP - some these will come out of the registry + IRDA_QOS_PARMS LocalQos; + BYTE DscvInfoBuf[64]; + int DscvInfoLen; + DWORD Val, Mask; + int i; +#define DISCOVERY_HINT_CHARSET 0x820400 +#define DISCOVERY_NICKNAME "Aoxomoxoa" +#define DISCOVERY_NICKNAME_LEN 9 +#define DISCOVERY_SLOTS 8 + + LocalQos.bfBaud = BPS_9600 | BPS_19200 | BPS_115200; + LocalQos.bfMaxTurnTime = MAX_TAT_500; + LocalQos.bfDataSize = DATA_SIZE_64|DATA_SIZE_128|DATA_SIZE_256; + LocalQos.bfWindowSize = FRAMES_1|FRAMES_2|FRAMES_3; + LocalQos.bfBofs = BOFS_3; + LocalQos.bfMinTurnTime = MIN_TAT_10; + LocalQos.bfDisconnectTime = DISC_TIME_12; + + Val = DISCOVERY_HINT_CHARSET; + + // Build the discovery info + DscvInfoLen = 0; + for (i = 0, Mask = 0xFF000000; i < 4; i++, Mask >>= 8) + { + if (Mask & Val || DscvInfoLen > 0) + { + DscvInfoBuf[DscvInfoLen++] = (BYTE) ((Mask & Val) >> (8 * (3-i))); + } + } + memcpy(DscvInfoBuf+DscvInfoLen, DISCOVERY_NICKNAME, DISCOVERY_NICKNAME_LEN); + DscvInfoLen += DISCOVERY_NICKNAME_LEN; + // TEMP ****************************************************** + // ******************************************************* + + DEBUGMSG(1, ("+IrdaBindAdapter() \"%ws\", BindContext %x\n", + AdapterName->Buffer, BindContext)); + + NdisAllocateMemory((PVOID *)&pIrdaLinkCb, sizeof(IRDA_LINK_CB), 0, pa); + + if (!pIrdaLinkCb) + { + *pStatus = STATUS_INSUFFICIENT_RESOURCES; + goto exit10; + } + + NdisZeroMemory(pIrdaLinkCb, sizeof(IRDA_LINK_CB)); + // Add a signature + NdisInitializeEvent(&pIrdaLinkCb->SyncEvent); + NdisResetEvent(&pIrdaLinkCb->SyncEvent); + NdisAllocateSpinLock(&pIrdaLinkCb->SpinLock); + + NdisAllocateBufferPool(pStatus, + &pIrdaLinkCb->BufferPool, + IRDA_NDIS_BUFFER_POOL_SIZE); + if (*pStatus != NDIS_STATUS_SUCCESS) + { + DEBUGMSG(DBG_ERROR, ("NdisAllocateBufferPool failed\n")); + goto error10; // free pIrdaLinkCB + } + + NdisAllocatePacketPool(pStatus, + &pIrdaLinkCb->PacketPool, + IRDA_NDIS_PACKET_POOL_SIZE, + sizeof(IRDA_PROTOCOL_RESERVED)-1 + \ + sizeof(NDIS_IRDA_PACKET_INFO)); + if (*pStatus != NDIS_STATUS_SUCCESS) + { + DEBUGMSG(DBG_ERROR, ("NdisAllocatePacketPool failed\n")); + goto error20; // free pIrdaLinkCb, Buffer pool + } + + NdisInitializeListHead(&pIrdaLinkCb->IMsgList); + + // For internally generated LAP messages + pIrdaLinkCb->IMsgListLen = 0; + for (i = 0; i < IRDA_MSG_LIST_LEN; i++) + { + NdisAllocateMemory(&pIMsg, sizeof(IRDA_MSG) + IRDA_MSG_DATA_SIZE, + 0, pa); + if (pIMsg == NULL) + { + *pStatus = STATUS_INSUFFICIENT_RESOURCES; + goto error40; + } + NdisInterlockedInsertTailList(&pIrdaLinkCb->IMsgList, + &pIMsg->Linkage, + &pIrdaLinkCb->SpinLock); + pIrdaLinkCb->IMsgListLen++; + } + + NdisOpenAdapter( + pStatus, + &OpenErrorStatus, + &pIrdaLinkCb->NdisBindingHandle, + &SelectedMediumIndex, + MediumArray, + 1, + NdisIrdaHandle, + pIrdaLinkCb, + AdapterName, + 0, + NULL); + + DEBUGMSG(DBG_NDIS, ("NdisOpenAdapter(), status %x\n", + pIrdaLinkCb->NdisBindingHandle, *pStatus)); + + if (*pStatus == NDIS_STATUS_PENDING) + { + NdisWaitEvent(&pIrdaLinkCb->SyncEvent, 0); + *pStatus = pIrdaLinkCb->SyncStatus; + } + + if (*pStatus != NDIS_STATUS_SUCCESS) + { + goto error30; // free pIrdaLinkCb, Buffer pool, Packet pool + } + + // Query adapters capabilities + + UintArrayCnt = sizeof(UintArray)/sizeof(UINT); + *pStatus = IrdaQueryOid(pIrdaLinkCb, + OID_IRDA_SUPPORTED_SPEEDS, + UintArray, &UintArrayCnt); + if (*pStatus != NDIS_STATUS_SUCCESS) + { + DEBUGMSG(DBG_ERROR, + ("Query IRDA_SUPPORTED_SPEEDS failed %x\n", + *pStatus)); + goto error30; + } + + OidToLapQos(vBaudTable, + UintArray, + UintArrayCnt, + &LocalQos.bfBaud); + + UintArrayCnt = sizeof(UintArray)/sizeof(UINT); + *pStatus = IrdaQueryOid(pIrdaLinkCb, + OID_IRDA_TURNAROUND_TIME, + UintArray, &UintArrayCnt); + + if (*pStatus != NDIS_STATUS_SUCCESS) + { + DEBUGMSG(DBG_ERROR, + ("Query IRDA_SUPPORTED_SPEEDS failed %x\n", + *pStatus)); + goto error30; + } + + OidToLapQos(vMinTATTable, + UintArray, + UintArrayCnt, + &LocalQos.bfMinTurnTime); + + IrlapOpenLink(pStatus, + pIrdaLinkCb, + &LocalQos, + DscvInfoBuf, + DscvInfoLen, + DISCOVERY_SLOTS); + + if (*pStatus != STATUS_SUCCESS) + { + goto error30; + } + + InsertTailList(&IrdaLinkCbList, &pIrdaLinkCb->Linkage); + + goto exit10; + +error40: + + pIMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList( + &pIrdaLinkCb->IMsgList, &pIrdaLinkCb->SpinLock); + + while (pIMsg != NULL) + { + NdisFreeMemory(pIMsg, sizeof(IRDA_MSG) + IRDA_MSG_DATA_SIZE, 0); + pIMsg = (IRDA_MSG *) NdisInterlockedRemoveHeadList( + &pIrdaLinkCb->IMsgList, &pIrdaLinkCb->SpinLock); + pIMsg = (IRDA_MSG *) RemoveHeadList(&pIrdaLinkCb->IMsgList); + } + +error30: + NdisFreePacketPool(pIrdaLinkCb->PacketPool); + +error20: + NdisFreeBufferPool(pIrdaLinkCb->BufferPool); + +error10: + + NdisFreeMemory(pIrdaLinkCb, sizeof(IRDA_LINK_CB), 0); + +exit10: + DEBUGMSG(DBG_NDIS, ("-IrdaBindAdapter() status %x\n", + *pStatus)); + + return; +} + +VOID IrdaUnbindAdapter( + OUT PNDIS_STATUS pStatus, + IN NDIS_HANDLE IrdaBindingContext, + IN NDIS_HANDLE UnbindContext + ) +{ + PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaBindingContext; + + DEBUGMSG(DBG_NDIS, ("+IrdaUnbindAdapter()\n")); + + NdisInitializeEvent(&pIrdaLinkCb->SyncEvent); + NdisResetEvent(&pIrdaLinkCb->SyncEvent); + + NdisCloseAdapter(pStatus, pIrdaLinkCb->NdisBindingHandle); + + if(*pStatus == NDIS_STATUS_PENDING) + { + NdisWaitEvent(&pIrdaLinkCb->SyncEvent, 0); + *pStatus = pIrdaLinkCb->SyncStatus; + } + + if (*pStatus == NDIS_STATUS_SUCCESS){ + NdisFreeMemory(pIrdaLinkCb, sizeof(IRDA_LINK_CB), 0); + } + + DEBUGMSG(DBG_NDIS, ("-IrdaUnbindAdapter() Status %x\n", + *pStatus)); + + return; +} + +VOID IrdaUnload( + VOID + ) +{ + DEBUGMSG(DBG_NDIS, ("+IrdaUnload()\n")); + + return; +} + +NTSTATUS IrdaNdisInitialize() +{ + NDIS_STATUS Status; + NDIS40_PROTOCOL_CHARACTERISTICS pc; + NDIS_STRING ProtocolName = NDIS_STRING_CONST("IRDA"); + UINT ProtocolReservedLength; + + DEBUGMSG(DBG_NDIS,("+IrdaNdisInitialize()\n")); + + NdisZeroMemory((PVOID)&pc, sizeof(NDIS40_PROTOCOL_CHARACTERISTICS)); + pc.MajorNdisVersion = 0x04; + pc.MinorNdisVersion = 0x00; + pc.OpenAdapterCompleteHandler = IrdaOpenAdapterComplete; + pc.CloseAdapterCompleteHandler = IrdaCloseAdapterComplete; + pc.SendCompleteHandler = IrdaSendComplete; + pc.TransferDataCompleteHandler = IrdaTransferDataComplete; + pc.ResetCompleteHandler = IrdaResetComplete; + pc.RequestCompleteHandler = IrdaRequestComplete; + pc.ReceiveHandler = IrdaReceive; + pc.ReceiveCompleteHandler = IrdaReceiveComplete; + pc.StatusHandler = IrdaStatus; + pc.StatusCompleteHandler = IrdaStatusComplete; + pc.BindAdapterHandler = IrdaBindAdapter; + pc.UnbindAdapterHandler = IrdaUnbindAdapter; + pc.UnloadHandler = IrdaUnload; + pc.Name = ProtocolName; + pc.ReceivePacketHandler = IrdaReceivePacket; + pc.TranslateHandler = NULL; + + NdisRegisterProtocol(&Status, + &NdisIrdaHandle, + (PNDIS_PROTOCOL_CHARACTERISTICS)&pc, + sizeof(NDIS40_PROTOCOL_CHARACTERISTICS)); + + // Do any LAP/LMP initialization here + + DEBUGMSG(DBG_NDIS, ("-IrdaNdisInitialize(), rc %x\n", Status)); + + return Status; +} + +UINT +MacConfigRequest( + PIRDA_LINK_CB pIrdaLinkCb, + PIRDA_MSG pMsg) +{ + switch (pMsg->IRDA_MSG_Op) + { + case MAC_INITIALIZE_LINK: + case MAC_RECONFIG_LINK: + pIrdaLinkCb->ExtraBofs = pMsg->IRDA_MSG_NumBOFs; + pIrdaLinkCb->MinTat = pMsg->IRDA_MSG_MinTat; + return IrdaSetOid(pIrdaLinkCb, + OID_IRDA_LINK_SPEED, + (UINT) pMsg->IRDA_MSG_Baud); + + case MAC_MEDIA_SENSE: + ASSERT(0); + + } + + return SUCCESS; + +} +UINT IrmacDown( + IN PVOID Context, + PIRDA_MSG pMsg) +{ + NDIS_STATUS Status; + PNDIS_PACKET NdisPacket = NULL; + PNDIS_BUFFER NdisBuffer = NULL; + PIRDA_PROTOCOL_RESERVED ProtocolReserved; + PNDIS_IRDA_PACKET_INFO IrdaPacketInfo; + PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) Context; + + DEBUGMSG(DBG_FUNCTION, ("+IrmacDown()\n")); + + + if (pMsg->Prim == MAC_CONTROL_REQ) + { + return MacConfigRequest(pIrdaLinkCb, pMsg); + } + + NdisAllocatePacket(&Status, &NdisPacket, pIrdaLinkCb->PacketPool); + if (Status != NDIS_STATUS_SUCCESS) + { + return 1; + } + + NdisAllocateBuffer(&Status, &NdisBuffer, pIrdaLinkCb->PacketPool, + pMsg->IRDA_MSG_pHdrRead, + pMsg->IRDA_MSG_pHdrWrite-pMsg->IRDA_MSG_pHdrRead); + if (Status != NDIS_STATUS_SUCCESS) + { + return 1; + } + NdisChainBufferAtFront(NdisPacket, NdisBuffer); + + NdisAllocateBuffer(&Status, &NdisBuffer, pIrdaLinkCb->PacketPool, + pMsg->IRDA_MSG_pRead, + pMsg->IRDA_MSG_pWrite-pMsg->IRDA_MSG_pRead); + if (Status != NDIS_STATUS_SUCCESS) + { + return 1; + } + NdisChainBufferAtBack(NdisPacket, NdisBuffer); + + ProtocolReserved = (PIRDA_PROTOCOL_RESERVED)(NdisPacket->ProtocolReserved); + + ProtocolReserved->pIMsg = pMsg; + + IrdaPacketInfo = (PNDIS_IRDA_PACKET_INFO) \ + (ProtocolReserved->MediaInfo.ClassInformation); + + IrdaPacketInfo->ExtraBOFs = pIrdaLinkCb->ExtraBofs; + IrdaPacketInfo->MinTurnAroundTime = pIrdaLinkCb->MinTat; + + NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(NdisPacket, + &ProtocolReserved->MediaInfo, + sizeof(MEDIA_SPECIFIC_INFORMATION) -1 + + sizeof(NDIS_IRDA_PACKET_INFO)); + NdisSend(&Status, pIrdaLinkCb->NdisBindingHandle, NdisPacket); + + return 0; +} diff --git a/private/ntos/tdi/irda/driver/makefile b/private/ntos/tdi/irda/driver/makefile new file mode 100644 index 000000000..58189757d --- /dev/null +++ b/private/ntos/tdi/irda/driver/makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/tdi/irda/driver/sources b/private/ntos/tdi/irda/driver/sources new file mode 100644 index 000000000..70d52d5e4 --- /dev/null +++ b/private/ntos/tdi/irda/driver/sources @@ -0,0 +1,15 @@ +TARGETNAME=irda +TARGETPATH=$(BASEDIR)\public\sdk\lib +TARGETTYPE=DRIVER + +TARGETLIBS= \ + $(BASEDIR)\public\sdk\lib\*\ndis.lib \ + $(BASEDIR)\public\sdk\lib\*\tdi.lib \ + ..\lib\*\irlap.lib + +INCLUDES=$(BASEDIR)\private\inc;$(BASEDIR)\private\ntos\inc;..\..\inc;..\inc + +C_DEFINES=$(C_DEFINES) -DNT -D_NTDRIVER_ -DIRDA + +SOURCES= irda.c \ + irndis.c diff --git a/private/ntos/tdi/irda/inc/af_irda.h b/private/ntos/tdi/irda/inc/af_irda.h new file mode 100644 index 000000000..5e5d36b0d --- /dev/null +++ b/private/ntos/tdi/irda/inc/af_irda.h @@ -0,0 +1,100 @@ +// +// this is the header file that describes the IRDA address family +// +// CREATED 4/28: AldenG +// + +#ifndef __AFIRDA__ +#define __AFIRDA__ + +#include + +#define AF_IRDA 22 // see winsock.h +#define PF_IRDA AF_IRDA + +#define SOL_IRLMP 0x00FF + +#define IRLMP_ENUMDEVICES 0x00000010 +#define IRLMP_IAS_SET 0x00000011 +#define IRLMP_IAS_QUERY 0x00000012 +#define IRLMP_SEND_PDU_LEN 0x00000013 +#define IRLMP_EXCLUSIVE_MODE 0x00000014 +#define IRLMP_IRLPT_MODE 0x00000015 +#define IRLMP_9WIRE_MODE 0x00000016 + +#define IAS_ATTRIB_NO_CLASS 0x00000010 +#define IAS_ATTRIB_NO_ATTRIB 0x00000000 +#define IAS_ATTRIB_INT 0x00000001 +#define IAS_ATTRIB_OCTETSEQ 0x00000002 +#define IAS_ATTRIB_STR 0x00000003 + +typedef struct _SOCKADDR_IRDA +{ + u_short irdaAddressFamily; + u_char irdaDeviceID[4]; + char irdaServiceName[25]; +} SOCKADDR_IRDA, *PSOCKADDR_IRDA; + +typedef struct _IRDA_DEVICE_INFO +{ + u_char irdaDeviceID[4]; + char irdaDeviceName[22]; + u_char Reserved[2]; +} IRDA_DEVICE_INFO, *PIRDA_DEVICE_INFO, FAR *LPIRDA_DEVICE_INFO; + +typedef struct _DEVICELIST +{ + ULONG numDevice; + IRDA_DEVICE_INFO Device[1]; +} DEVICELIST, *PDEVICELIST, FAR *LPDEVICELIST; + +typedef struct _IAS_SET +{ + char irdaClassName[61]; + char irdaAttribName[61]; + u_short irdaAttribType; + union + { + int irdaAttribInt; + struct + { + int Len; + u_char OctetSeq[1]; + u_char Reserved[3]; + } irdaAttribOctetSeq; + struct + { + int Len; + u_char CharSet; + u_char UsrStr[1]; + u_char Reserved[2]; + } irdaAttribUsrStr; + } irdaAttribute; +} IAS_SET, *PIAS_SET, FAR *LPIAS_SET; + +typedef struct _IAS_QUERY +{ + u_char irdaDeviceID[4]; + char irdaClassName[61]; + char irdaAttribName[61]; + u_short irdaAttribType; + union + { + int irdaAttribInt; + struct + { + int Len; + u_char OctetSeq[1]; + u_char Reserved[3]; + } irdaAttribOctetSeq; + struct + { + int Len; + u_char CharSet; + u_char UsrStr[1]; + u_char Reserved[2]; + } irdaAttribUsrStr; + } irdaAttribute; +} IAS_QUERY, *PIAS_QUERY, FAR *LPIAS_QUERY; + +#endif // __AFIRDA__ diff --git a/private/ntos/tdi/irda/inc/decdirda.h b/private/ntos/tdi/irda/inc/decdirda.h new file mode 100644 index 000000000..d93b0d9e3 --- /dev/null +++ b/private/ntos/tdi/irda/inc/decdirda.h @@ -0,0 +1,174 @@ +// returns pointers pOutStr +TCHAR *DecodeIRDA(int *pFrameType,// return frame type (-1 = bad frame) + BYTE *pFrameBuf, // pointer to buffer containing IRLAP frame + UINT FrameLen, // length of buffer + TCHAR *pOutStr, // string where decode packet is placed + UINT DecodeLayer,// 2-LAP only, 3-LAP/LMP, 4-LAP/LMP/TTP + BOOL fNoConnAddr,// TRUE->Don't show connection address in str + int DispMode // DISP_ASCII/HEX/BOTH +); + +#define DISP_ASCII 1 +#define DISP_HEX 2 +#define DISP_BOTH 3 + +extern int BaudBitMask; + +#define IRLAP_BOF 0xC0 +#define IRLAP_EOF 0xC1 +#define IRLAP_ESC 0x7D +#define IRLAP_COMP_BIT 0x20 + +#define IRLAP_BROADCAST 0xfe +#define _IRLAP_CMD 0x01 +#define _IRLAP_RSP 0x00 + +#define IRLAP_I_FRM 0x00 +#define IRLAP_S_FRM 0x01 +#define IRLAP_U_FRM 0x03 + +/* +** Unnumbered Frame types with P/F bit set to 0 +*/ +#define IRLAP_UI 0x03 +#define IRLAP_XID_CMD 0x2f +#define IRLAP_TEST 0xe3 +#define IRLAP_SNRM 0x83 +#define IRLAP_DISC 0x43 +#define IRLAP_UA 0x63 +#define IRLAP_FRMR 0x87 +#define IRLAP_DM 0x0f +#define IRLAP_XID_RSP 0xaf + +/* +** Supervisory Frames +*/ +#define IRLAP_RR 0x01 +#define IRLAP_RNR 0x05 +#define IRLAP_REJ 0x09 +#define IRLAP_SREJ 0x0d + + +#define IRLAP_GET_ADDR(addr) (addr >> 1) +#define IRLAP_GET_CRBIT(addr) (addr & 1) +#define IRLAP_GET_PFBIT(cntl) ((cntl >>4) & 1) +#define IRLAP_GET_UCNTL(cntl) (cntl & 0xEF) +#define IRLAP_GET_SCNTL(cntl) (cntl & 0x0F) +#define IRLAP_FRAME_TYPE(cntl) (cntl & 0x01 ? (cntl & 3) : 0) +#define IRLAP_GET_NR(cntl) ((cntl & 0xE0) >> 5) +#define IRLAP_GET_NS(cntl) ((cntl & 0xE) >> 1) + +/* +** XID stuff +*/ +#define XID_DISCV_FORMAT_ID 0x01 +#define XID_NEGPARMS_FORMAT_ID 0x02 + +typedef struct +{ + BYTE SrcAddr[4]; + BYTE DestAddr[4]; + BYTE NoOfSlots:2; + BYTE GenNewAddr:1; + BYTE Reserved:5; + BYTE SlotNo; + BYTE Version; +} XID_DISCV_FORMAT; + +/* +** SNRM +*/ +typedef struct +{ + BYTE SrcAddr[4]; + BYTE DestAddr[4]; + BYTE ConnAddr; + BYTE FirstPI; +} SNRM_FORMAT; + +/* +** UA +*/ +typedef struct +{ + BYTE SrcAddr[4]; + BYTE DestAddr[4]; + BYTE FirstPI; +} UA_FORMAT; + +/* +** LM-PDU stuff +*/ +typedef struct +{ + BYTE DLSAP_SEL:7; + BYTE CntlBit:1; + BYTE SLSAP_SEL:7; + BYTE RsvrdBi1:1; +} LM_HEADER; + +/* LM-PDU frame types */ +#define LM_PDU_CNTL_FRAME 1 +#define LM_PDU_DATA_FRAME 0 + +typedef struct +{ + BYTE OpCode:7; + BYTE ABit:1; +} LM_CNTL_FORMAT; + +/* Opcodes */ +#define LM_PDU_CONNECT 1 +#define LM_PDU_DISCONNECT 2 +#define LM_PDU_ACCESSMODE 3 + +#define LM_PDU_REQUEST 0 +#define LM_PDU_CONFIRM 1 + +#define LM_PDU_SUCCESS 0 +#define LM_PDU_FAILURE 1 +#define LM_PDU_UNSUPPORTED 0xFF + +#define LM_PDU_MULTIPLEXED 0 +#define LM_PDU_EXCLUSIVE 1 + +/* Max disconnect reason code, see _LM_PDU_DscReason[] in decdirda.c */ +#define LM_PDU_MAX_DSC_REASON 0x8 + +/* +** Negotiation Parameter Identifiers +*/ +#define NEG_PI_BAUD 0x01 +#define NEG_PI_MAX_TAT 0x82 +#define NEG_PI_DATA_SZ 0x83 +#define NEG_PI_WIN_SZ 0x84 +#define NEG_PI_BOFS 0x85 +#define NEG_PI_MIN_TAT 0x86 +#define NEG_PI_DISC_THRESH 0x08 + +// Tiny TP! + +#define TTP_PFLAG_NO_PARMS 0 +#define TTP_PFLAG_PARMS 1 + +#define TTP_MBIT_NOT_FINAL 1 +#define TTP_MBIT_FINAL 0 + +typedef struct +{ + BYTE InitialCredit : 7; + BYTE ParmFlag : 1; +} TTP_CONN_HEADER; + +typedef struct +{ + BYTE AdditionalCredit : 7; + BYTE MoreBit : 1; +} TTP_DATA_HEADER; + +#define net_short(x) ((((x)&0xff) << 8) | (((x)&0xff00) >> 8)) + +#define net_long(x) (((((DWORD UNALIGNED)(x))&0xffL)<<24) | \ + ((((DWORD UNALIGNED)(x))&0xff00L)<<8) | \ + ((((DWORD UNALIGNED)(x))&0xff0000L)>>8) | \ + ((((DWORD UNALIGNED)(x))&0xff000000L)>>24)) diff --git a/private/ntos/tdi/irda/inc/irda.h b/private/ntos/tdi/irda/inc/irda.h new file mode 100644 index 000000000..ab9d55674 --- /dev/null +++ b/private/ntos/tdi/irda/inc/irda.h @@ -0,0 +1,857 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irda.h +* +* Description: Definitions used across the IRDA stack +* +* Author: mbert +* +* Date: 4/15/95 +* +* This file primarily defines the IRDA message (IRDA_MSG) used for +* communicating with the stack and communication between the layers +* of the stack. IRDA_MSG provides the following services: +* MAC_CONTROL_SERVICE +* IRLAP_DISCOVERY_SERVICE +* IRDA_DISCONNECT_SERVICE +* IRDA_CONNECT_SERVICE +* IRDA_DATA_SERVICE +* IRLMP_ACCESSMODE_SERVICE +* IRLMP_IAS_SERVICE +* +* IRDA_MSG usage: +* +* +-------+ +* | IRLAP | +* +-------+ +* | +* | IRMAC_Down(IRDA_MSG) +* \|/ +* +-------+ +* | IRMAC | +* +-------+ +* |**************************************************************************| +* | Prim | MsgType and parameters | +* |==========================================================================| +* | MAC_DATA_REQ | IRDA_DATA_SERVICE | +* | | o IRDA_MSG_pHdrRead = start of IRDA headers | +* | | o IRDA_MSG_pHdrWrite = end of header | +* | | o IRDA_MSG_pRead = start of data | +* | | o IRDA_MSG_pWrite = end of data | +* |--------------------------+-----------------------------------------------| +* | MAC_CONTROL_REQ | MAC_CONTROL_SERVICE | +* | | o IRDA_MSG_Op = MAC_INITIALIZIE_LINK | +* | | - IRDA_MSG_Port | +* | | - IRDA_MSG_Baud | +* | | - IRDA_MSG_MinTat = min turn time | +* | | - IRDA_MSG_NumBOFs = # added when tx'ing | +* | | - IRDA_MSG_DataSize = max rx frame | +* | | - IRDA_MSG_SetIR = TRUE/FALSE (does an | +* | | EscapeComm(SETIR) to select int/ext | +* | | dongle) | +* | | o IRDA_MSG_Op = MAC_MEDIA_SENSE | +* | | - IRDA_MSG_SenseTime (in ms) | +* | | o IRDA_MSG_Op = MAC_RECONFIG_LINK | +* | | - IRDA_MSG_Baud | +* | | - IRDA_MSG_NumBOFs = # added when tx'ing | +* | | - IRDA_MSG_DataSize = max rx frame | +* | | - IRDA_MSG_MinTat = min turn time | +* | | o IRDA_MSG_OP = MAC_SHUTDOWN_LINK | +* |--------------------------------------------------------------------------| +* +* +-------+ +* | IRLAP | +* +-------+ +* /|\ +* | IRLAP_Up(IRDA_MSG) +* | +* +-------+ +* | IRMAC | +* +-------+ +* |**************************************************************************| +* | Prim | MsgType and parameters | +* |==========================================================================| +* | MAC_DATA_IND | IRDA_DATA_SERVICE | +* | | o IRDA_MSG_pRead = start of frame | +* | | (includes IRLAP header) | +* | | o IRDA_MSG_pWrite = end of frame | +* | | (excludes FCS) | +* |--------------------------+-----------------------------------------------| +* | MAC_CONTROL_CONF | MAC_CONTROL_SERVICE | +* | | o IRDA_MSG_Op = MAC_MEDIA_SENSE | +* | | - IRDA_MSG_OpStatus = MAC_MEDIA_BUSY | +* | | MAC_MEDIA_CLEAR | +* |--------------------------------------------------------------------------| +* +* +-------+ +* | IRLMP | +* +-------+ +* | +* | IRLAP_Down(IRDA_MSG) +* \|/ +* +-------+ +* | IRLAP | +* +-------+ +* |**************************************************************************| +* | Prim | MsgType and parameters | +* |==========================================================================| +* | IRLAP_DISCOVERY_REQ | IRLAP_DISCOVERY_SERVICE | +* | IRLAP_Down() returns | o IRDA_MSG_SenseMedia = TRUE/FALSE | +* | IRLAP_REMOTE_DISCOVERY_IN_PROGRESS_ERR or | +* | IRLAP_REMOTE_CONNECT_IN_PROGRESS_ERR when indicated | +* |--------------------------+-----------------------------------------------| +* | IRLAP_CONNECT_REQ | IRDA_CONNECT_SERVICE | +* | | o IRDA_MSG_RemoteDevAddr | +* | IRLAP_Down() returns | | +* | IRLAP_REMOTE_DISCOVERY_IN_PROGRESS_ERR when indicated | +* |--------------------------+-----------------------------------------------| +* | IRLAP_CONNECT_RESP | no parms | +* |--------------------------+-----------------------------------------------| +* | IRLAP_DISCONNECT_REQ | no parms | +* |--------------------------+-----------------------------------------------| +* | IRLAP_DATA_REQ | IRDA_DATA_SERVICE | +* | IRLAP_UDATA_REQ | o IRDA_MSG_pHdrRead = start of IRLMP header | +* | IRLAP_Down() returns | o IRDA_MSG_pHdrWrite = end of header | +* | IRLAP_REMOTE_BUSY to | o IRDA_MSG_pRead = start of data | +* | to flow off LMP. | o IRDA_MSG_pWrite = end of data | +* |--------------------------------------------------------------------------| +* | IRLAP_FLOWON_REQ | no parms | +* |--------------------------------------------------------------------------| +* +* +-------+ +* | IRLMP | +* +-------+ +* /|\ +* | IRLMP_Up(IRDA_MSG) +* | +* +-------+ +* | IRLAP | +* +-------+ +* |**************************************************************************| +* | Prim | MsgType and parameters | +* |==========================================================================| +* | IRLAP_DISCOVERY_IND | IRLAP_DISCOVERY_SERVICE | +* | | o pDevList = Discovery info of device that | +* | | initiated discovery | +* |--------------------------+-----------------------------------------------| +* | IRLAP_DISCOVERY_CONF | IRLAP_DISCOVERY_SERVICE | +* | | o IRDA_MSG_pDevList = list of discovered | +* | | devices, NULL when | +* | | status != IRLAP_DISCOVERY_COMPLETED | +* | | o IRDA_MSG_DscvStatus = | +* | | MAC_MEDIA_BUSY | +* | | IRLAP_REMOTE_DISCOVERY_IN_PROGRESS | +* | | IRLAP_DISCOVERY_COLLISION | +* | | IRLAP_REMOTE_CONNECTION_IN_PROGRESS | +* | | IRLAP_DISCOVERY_COMPLETED | +* |--------------------------+-----------------------------------------------| +* | IRLAP_CONNECT_IND | IRDA_CONNECT_SERVICE | +* | | o IRDA_MSG_RemoteDevAddr | +* | | o IRDA_MSG_pQOS = Negotiated QOS | +* |--------------------------------------------------------------------------| +* | IRLAP_CONNECT_CONF | IRDA_CONNECT_SERVICE | +* | | o IRDA_MSG_pQOS = Negotiated QOS, only when | +* | | successful | +* | | o IRDA_MSG_ConnStatus = | +* | | IRLAP_CONNECTION_COMPLETE | +* |--------------------------+-----------------------------------------------| +* | IRLAP_DISCONNECT_IND | IRDA_DISCONNECT_SERVICE | +* | | o IRDA_MSG_DiscStatus = | +* | | IRLAP_DISCONNECT_COMPLETED | +* | | IRLAP_REMOTED_INITIATED | +* | | IRLAP_PRIMARY_CONFLICT | +* | | IRLAP_REMOTE_DISCOVERY_IN_PROGRESS | +* | | IRLAP_NO_RESPONSE | +* | | IRLAP_DECLINE_RESET | +* | | MAC_MEDIA_BUSY | +* |--------------------------+-----------------------------------------------| +* | IRLAP_DATA_IND | IRDA_DATA_SERVICE | +* | IRLAP_UDATA_IND | o IRDA_MSG_pRead = start of IRLMP packet | +* | | o IRDA_MSG_pWrite = end of IRLMP packet | +* |--------------------------+-----------------------------------------------| +* | IRLAP_DATA_CONF | IRDA_DATA_SERVICE | +* | IRLAP_UDATA_CONF | o IRDA_MSG_DataStatus = | +* | | ILAP_DATA_REQUEST_COMPLETED | +* | | IRLAP_DATA_REQUEST_FAILED_LINK_RESET | +* |--------------------------+-----------------------------------------------| +* | IRLAP_STATUS_IND | no parms | +* |--------------------------------------------------------------------------| +* +* +--------------+ +* | TransportAPI | +* +--------------+ +* | +* | IRLMP_Down(IRLMPContext, IRDA_MSG) +* \|/ +* +-------+ +* | IRLMP | +* +-------+ +* |**************************************************************************| +* | Prim | MsgType and parameters | +* |==========================================================================| +* | IRLMP_DISCOVERY_REQ | no parms | +* |--------------------------+-----------------------------------------------| +* | IRLMP_CONNECT_REQ | IRDA_CONNECT_SERVICE | +* | IRLMP_Down() returns | o IRDA_MSG_RemoteDevAddr | +* | IRLMP_LINK_IN_USE | o IRDA_MSG_RemoteLSAPSel | +* | when the requested | o IRDA_MSG_pQOS (may be NULL) | +* | connection is to a | o IRDA_MSG_pConnData | +* | remote device other | o IRDA_MSG_ConnDataLen | +* | than the one the link | o IRDA_MSG_LocalLSAPSel | +* | is currently connected | o IRDA_MSG_pContext | +* | or connecting to. | o IRDA_MSG_UseTTP | +* | | o IRDA_MSG_TTPCredits | +* | | o IRDA_MSG_MaxSDUSize - Max size that this | +* | | IRLMP client can receive. | +* |--------------------------+-----------------------------------------------| +* | IRLMP_CONNECT_RESP | IRDA_CONNECT_SERVICE | +* | | o IRDA_MSG_pConnData | +* | | o IRDA_MSG_ConnDataLen | +* | | o IRDA_MSG_pContext | +* | | o IRDA_MSG_MaxSDUSize - Max size that this | +* | | IRLMP client can receive. | +* | | o IRDA_MSG_TTPCredits | +* |--------------------------+-----------------------------------------------| +* | IRLMP_DISCONNECT_REQ | IRDA_DISCONNECT_SERVICE | +* | | o IRDA_MSG_pDiscData | +* | | o IRDA_MSG_DiscDataLen | +* | | | +* | | | +* |--------------------------+-----------------------------------------------| +* | IRLMP_DATA/UDATA_REQ | IRDA_DATA_SERVICE | +* | IRLMP_Down() may return| o IRDA_MSG_pDataContext = ptr to NDIS_BUFFER| +* | IRLMP_REMOTE_BUSY, | o IRDA_MSG_IrCOMM_9Wire = TRUE/FALSE | +* | when tx cred exhausted| | +* | in multiplexed mode. | | +* | IRLAP_REMOTE_BUSY, | | +* | when remote IRLAP | | +* | flowed off in exclMode| | +* | In either case the req | | +* | was successful. | | +* |--------------------------------------------------------------------------| +* | IRLMP_ACCESSMODE_REQ | IRLMP_ACCESSMODE_SERVICE | +* | IRLMP_Down() may return| o IRDA_MSG_AccessMode = IRLMP_MULTIPLEXED | +* | IRLMP_IN_EXCLUSIVE_MODE| IRLMP_EXCLUSIVE | +* | if already in excl-mode| o IRDA_MSG_IrLPTMode - TRUE, doesn't send | +* | IRLMP_IN_MULTIPLEXED...| the Access PDU | +* | if other LSAPs exist or| | +* | requesting trans to this state when already in it. | +* |--------------------------------------------------------------------------| +* | IRLMP_FLOWON_REQ | no parms | +* |--------------------------------------------------------------------------| +* | IRLMP_MORECREDIT_REQ | IRDA_CONNECT_SERVICE (cuz parm is defined) | +* | | o IRDA_MSG_TTPCredits | +* |--------------------------------------------------------------------------| +* | IRLMP_GETVALUEBYCLASS_REQ| IRDA_IAS_SERVICE | +* | | o IRDA_MSG_pIASQuery | +* | | o IRDA_MSG_AttribLen | +* | | o IRDA_MSG_IASQueryPerms | +* |--------------------------------------------------------------------------| +* +* +* +--------------+ +* | TransportAPI | +* +--------------+ +* /|\ +* | TransportAPI_Up(TransportAPIContext, IRDA_MSG) +* | +* +-------+ +* | IRLMP | +* +-------+ +* |**************************************************************************| +* | Prim | MsgType and parameters | +* |==========================================================================| +* | IRLAP_DISCOVERY_IND | IRLAP_DISCOVERY_SERVICE | +* | | o pDevList = aged Discovery list | +* |--------------------------+-----------------------------------------------| +* | IRLMP_DISCOVERY_CONF | same as IRLAP_DISCOVERY_CONF. The device list | +* | | however is the one maintained in IRLMP | +* |--------------------------+-----------------------------------------------| +* | IRLMP_DISCONNECT_IND | IRDA_DISCONNECT_SERVICE | +* | | o IRDA_MSG_DiscReason = | +* | | see IRLMP_DISC_REASON below | +* | | o IRDA_MSG_pDiscData - may be NULL | +* | | o IRDA_MSG_DiscDataLen | +* |--------------------------+-----------------------------------------------| +* | IRLMP_CONNECT_IND | IRDA_CONNECT_SERVICE | +* | | o IRDA_MSG_RemoteDevAddr | +* | | o IRDA_MSG_RemoteLSAPSel; | +* | | o IRDA_MSG_LocalLSAPSel; | +* | | o IRDA_MSG_pQOS | +* | | o IRDA_MSG_pConnData | +* | | o IRDA_MSG_ConnDataLen | +* | | o IRDA_MSG_pContext | +* | | o IRDA_MSG_MaxSDUSize - Max size that this | +* | | IRLMP client can send to peer | +* | | o IRDA_MSG_MaxPDUSize | +* |--------------------------+-----------------------------------------------| +* | IRLMP_CONNECT_CONF | IRDA_CONNECT_SERVICE | +* | | o IRDA_MSG_pQOS | +* | | o IRDA_MSG_pConnData | +* | | o IRDA_MSG_ConnDataLen | +* | | o IRDA_MSG_pContext | +* | | o IRDA_MSG_MaxSDUSize - Max size that this | +* | | IRLMP client can send to peer | +* | | o IRDA_MSG_MaxPDUSize | +* |--------------------------+-----------------------------------------------| +* | IRLMP_DATA_IND | IRDA_DATA_SERVICE | +* | | o IRDA_MSG_pRead = start of User Data | +* | | o IRDA_MSG_pWrite = end of User Data | +* | | o IRDA_MSG_FinalSeg = TRUE/FALSE | +* |--------------------------+-----------------------------------------------| +* | IRLMP_DATA_CONF | IRDA_DATA_SERVICE | +* | | o IRDA_MSG_pDataContext = ptr to NDIS_BUFFER| +* | | o IRDA_MSG_DataStatus = | +* | | IRLMP_DATA_REQUEST_COMPLETED | +* | | IRLMP_DATA_REQUEST_FAILED | +* |--------------------------+-----------------------------------------------| +* | IRLMP_ACCESSMODE_IND | IRLMP_ACCESSMODE_SERVICE | +* | | o IRDA_MSG_AccessMode = | +* | | IRLMP_EXCLUSIVE | +* | | IRLMP_MULTIPLEXED | +* |--------------------------+-----------------------------------------------| +* | IRLMP_ACCESSMODE_CONF | IRLMP_ACCESSMODE_SERVICE | +* | | o IRDA_MSG_AccessMode = | +* | | IRLMP_EXCLUSIVE | +* | | IRLMP_MULTIPLEXED | +* | | o IRDA_MSG_ModeStatus = | +* | | IRLMP_ACCESSMODE_SUCCESS | +* | | IRLMP_ACCESSMODE_FAILURE | +* |--------------------------+-----------------------------------------------| +* |IRLMP_GETVALUEBYCLASS_CONF| IRDA_DATA_SERVICE | +* | | o IRDA_MSG_pIASQuery | +* | | o IRDA_MSG_IASStatus = An IRLMP_DISC_REASON | +* | | (see below) | +* |--------------------------------------------------------------------------| +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#include + +#define TEMPERAMENTAL_SERIAL_DRIVER // drivers busted. intercharacter delays cause + // IrLAP to reset. + +#ifdef DEBUG +// Prototypes for Debugging Output +void IRDA_DebugOut (TCHAR *pFormat, ...); +void IRDA_DebugStartLog (void); +void IRDA_DebugEndLog (void *, void *); +#endif + +// Debug zone definitions. +/* +#define ZONE_IRDA DEBUGZONE(0) +#define ZONE_IRLAP DEBUGZONE(2) +#ifdef PEG +#define ZONE_IRMAC DEBUGZONE(1) +#define ZONE_IRLMP DEBUGZONE(3) +#define ZONE_IRLMP_CONN DEBUGZONE(4) +#define ZONE_IRLMP_CRED DEBUGZONE(5) +#else +extern int ZONE_IRMAC; +extern int ZONE_IRLMP; +extern int ZONE_IRLMP_CONN; +extern int ZONE_IRLMP_CRED; +#endif +#define ZONE_DISCOVER DEBUGZONE(8) +#define ZONE_PRINT DEBUGZONE(9) +#define ZONE_ADDR DEBUGZONE(10) +#define ZONE_MISC DEBUGZONE(11) +#define ZONE_ALLOC DEBUGZONE(12) +#define ZONE_FUNCTION DEBUGZONE(13) +#define ZONE_WARN DEBUGZONE(14) +#define ZONE_ERROR DEBUGZONE(15) +*/ + + +#define IRDA_ALLOC_MEM(ptr, sz, id) ((ptr) = CTEAllocMem(sz)) +#define IRDA_FREE_MEM(ptr) CTEFreeMem((ptr)) + +//extern CRITICAL_SECTION IrdaCS; + +// Time how low we wait for the critical section +/* +#define ENTER_IRDA_WITH_CRITICAL_SECTION(s) do { \ + LPWSTR Owner = IrdaCSOwner; \ + DWORD StartTick = GetTickCount(); \ + EnterCriticalSection (&IrdaCS); \ + IrdaCSOwner = s; \ + StartTick = GetTickCount() - StartTick; \ + if (StartTick > MaxWaitIrdaCS) { \ + DEBUGMSG (1, (TEXT("%s: IRDA Wait for CS %dms (Owner=%s)\r\n"), \ + s, StartTick, Owner)); \ + MaxWaitIrdaCS = StartTick; \ + } \ + } while (0) + + +#define LEAVE_IRDA_WITH_CRITICAL_SECTION IrdaCSOwner = TEXT(""), LeaveCriticalSection(&IrdaCS) + +#else // TIME_CS +#define ENTER_IRDA_WITH_CRITICAL_SECTION(s) EnterCriticalSection(&IrdaCS) + +#define LEAVE_IRDA_WITH_CRITICAL_SECTION LeaveCriticalSection(&IrdaCS) +#endif // TIME_CS +*/ +#define STATIC static + +#define RetOnErr(func) do {if((_rc = func) != SUCCESS) return _rc;} while(0) + +typedef struct +{ + CTETimer CteTimer; + VOID (*ExpFunc)(PVOID Context); + PVOID Context; + UINT Timeout; + BOOL Late; +#ifdef DEBUG + char *pName; +#endif +} IRDA_TIMER, *PIRDA_TIMER; + +#define IRMAC_CONTEXT(ilcb) ((ilcb)->IrmacContext) +#define IRLAP_CONTEXT(ilcb) ((ilcb)->IrlapContext) +#define IRLMP_CONTEXT(ilcb) ((ilcb)->IrlmpContext) + +// Device/Discovery Information +#define IRLAP_DSCV_INFO_LEN 32 +#define IRDA_DEV_ADDR_LEN 4 + +typedef struct +{ + LIST_ENTRY Linkage; + BYTE DevAddr[IRDA_DEV_ADDR_LEN]; + int DscvMethod; + int IRLAP_Version; + BYTE DscvInfo[IRLAP_DSCV_INFO_LEN]; + int DscvInfoLen; + int NotSeenCnt; // used by IRLMP to determine when to remove + // the device from its list + PVOID LinkContext; // Link on which device was discovered +} IRDA_DEVICE; + +// IRLAP Quality of Service +#define BIT_0 1 +#define BIT_1 2 +#define BIT_2 4 +#define BIT_3 8 +#define BIT_4 16 +#define BIT_5 32 +#define BIT_6 64 +#define BIT_7 128 +#define BIT_8 256 + +#define BPS_2400 BIT_0 // Baud Rates +#define BPS_9600 BIT_1 +#define BPS_19200 BIT_2 +#define BPS_38400 BIT_3 +#define BPS_57600 BIT_4 +#define BPS_115200 BIT_5 +#define BPS_4000000 BIT_8 + +#define MAX_TAT_500 BIT_0 // Maximum Turnaround Time (millisecs) +#define MAX_TAT_250 BIT_1 +#define MAX_TAT_100 BIT_2 +#define MAX_TAT_50 BIT_3 +#define MAX_TAT_25 BIT_4 +#define MAX_TAT_10 BIT_5 +#define MAX_TAT_5 BIT_6 + +#define DATA_SIZE_64 BIT_0 // Data Size (bytes) +#define DATA_SIZE_128 BIT_1 +#define DATA_SIZE_256 BIT_2 +#define DATA_SIZE_512 BIT_3 +#define DATA_SIZE_1024 BIT_4 +#define DATA_SIZE_2048 BIT_5 + +#define FRAMES_1 BIT_0 // Window Size +#define FRAMES_2 BIT_1 +#define FRAMES_3 BIT_2 +#define FRAMES_4 BIT_3 +#define FRAMES_5 BIT_4 +#define FRAMES_6 BIT_5 +#define FRAMES_7 BIT_6 + +#define BOFS_48 BIT_0 // Additional Beginning of Frame Flags +#define BOFS_24 BIT_1 +#define BOFS_12 BIT_2 +#define BOFS_5 BIT_3 +#define BOFS_3 BIT_4 +#define BOFS_2 BIT_5 +#define BOFS_1 BIT_6 +#define BOFS_0 BIT_7 + +#define MIN_TAT_10 BIT_0 // Minumum Turnaround Time (millisecs) +#define MIN_TAT_5 BIT_1 +#define MIN_TAT_1 BIT_2 +#define MIN_TAT_0_5 BIT_3 +#define MIN_TAT_0_1 BIT_4 +#define MIN_TAT_0_05 BIT_5 +#define MIN_TAT_0_01 BIT_6 +#define MIN_TAT_0 BIT_7 + +#define DISC_TIME_3 BIT_0 // Link Disconnect/Threshold Time (seconds) +#define DISC_TIME_8 BIT_1 +#define DISC_TIME_12 BIT_2 +#define DISC_TIME_16 BIT_3 +#define DISC_TIME_20 BIT_4 +#define DISC_TIME_25 BIT_5 +#define DISC_TIME_30 BIT_6 +#define DISC_TIME_40 BIT_7 + +typedef struct +{ + UINT bfBaud; + UINT bfMaxTurnTime; + UINT bfDataSize; + UINT bfWindowSize; + UINT bfBofs; + UINT bfMinTurnTime; + UINT bfDisconnectTime; // holds threshold time also +} IRDA_QOS_PARMS; + + +// IrDA Message Primitives +typedef enum +{ + MAC_DATA_REQ = 0, // Keep in sync with table in irlaplog.c + MAC_DATA_IND, + MAC_CONTROL_REQ, + MAC_CONTROL_CONF, + IRLAP_DISCOVERY_REQ, + IRLAP_DISCOVERY_IND, + IRLAP_DISCOVERY_CONF, + IRLAP_CONNECT_REQ, + IRLAP_CONNECT_IND, + IRLAP_CONNECT_RESP, + IRLAP_CONNECT_CONF, + IRLAP_DISCONNECT_REQ, + IRLAP_DISCONNECT_IND, + IRLAP_DATA_REQ, // Don't fuss with the order, CONF must be 2 from REQ + IRLAP_DATA_IND, + IRLAP_DATA_CONF, + IRLAP_UDATA_REQ, + IRLAP_UDATA_IND, + IRLAP_UDATA_CONF, + IRLAP_STATUS_IND, + IRLAP_FLOWON_REQ, + IRLAP_FLOWON_IND, + IRLMP_DISCOVERY_REQ, + IRLMP_DISCOVERY_IND, + IRLMP_DISCOVERY_CONF, + IRLMP_CONNECT_REQ, + IRLMP_CONNECT_IND, + IRLMP_CONNECT_RESP, + IRLMP_CONNECT_CONF, + IRLMP_DISCONNECT_REQ, + IRLMP_DISCONNECT_IND, + IRLMP_DATA_REQ, + IRLMP_DATA_IND, + IRLMP_DATA_CONF, + IRLMP_UDATA_REQ, + IRLMP_UDATA_IND, + IRLMP_UDATA_CONF, + IRLMP_ACCESSMODE_REQ, + IRLMP_ACCESSMODE_IND, + IRLMP_ACCESSMODE_CONF, + IRLMP_FLOWON_REQ, + IRLMP_FLOWON_IND, + IRLMP_MORECREDIT_REQ, + IRLMP_GETVALUEBYCLASS_REQ, + IRLMP_GETVALUEBYCLASS_CONF +} IRDA_SERVICE_PRIM; + +typedef enum +{ + MAC_MEDIA_BUSY, // keep in sync with IRDA_StatStr in irlaplog.c + MAC_MEDIA_CLEAR, + IRLAP_DISCOVERY_COLLISION, + IRLAP_REMOTE_DISCOVERY_IN_PROGRESS, + IRLAP_REMOTE_CONNECT_IN_PROGRSS, + IRLAP_DISCOVERY_COMPLETED, + IRLAP_REMOTE_CONNECTION_IN_PROGRESS, + IRLAP_CONNECTION_COMPLETED, + IRLAP_REMOTE_INITIATED, + IRLAP_PRIMARY_CONFLICT, + IRLAP_DISCONNECT_COMPLETED, + IRLAP_NO_RESPONSE, + IRLAP_DECLINE_RESET, + IRLAP_DATA_REQUEST_COMPLETED, + IRLAP_DATA_REQUEST_FAILED_LINK_RESET, + IRLAP_DATA_REQUEST_FAILED_REMOTE_BUSY, + IRLMP_NO_RESPONSE, + IRLMP_ACCESSMODE_SUCCESS, + IRLMP_ACCESSMODE_FAILURE, + IRLMP_DATA_REQUEST_COMPLETED, + IRLMP_DATA_REQUEST_FAILED +} IRDA_SERVICE_STATUS; + +// MAC Control Service Request Message - MAC_CONTROL_REQ/CONF +typedef enum +{ + MAC_INITIALIZE_LINK, // keep in sync with MAC_OpStr in irlaplog.c + MAC_SHUTDOWN_LINK, + MAC_RECONFIG_LINK, + MAC_MEDIA_SENSE, +} MAC_CONTROL_OPERATION; + +typedef struct +{ + MAC_CONTROL_OPERATION Op; + int Port; + int Baud; + int NumBOFs; + int MinTat; + int DataSize; + int SenseTime; + IRDA_SERVICE_STATUS OpStatus; + BOOL SetIR; +} MAC_CONTROL_SERVICE; + +// IRLAP Discovery Service Request Message - IRLAP_DISCOVERY_IND/CONF +typedef struct +{ + LIST_ENTRY *pDevList; + IRDA_SERVICE_STATUS DscvStatus; + BOOL SenseMedia; +} IRLAP_DISCOVERY_SERVICE; + +// IRDA Connection Service Request Message - IRLAP_CONNECT_REQ/IND/CONF +// IRLMP_CONNECT_REQ/CONF +typedef struct +{ + BYTE RemoteDevAddr[IRDA_DEV_ADDR_LEN]; + IRDA_QOS_PARMS *pQOS; + int LocalLSAPSel; + int RemoteLSAPSel; + BYTE *pConnData; + int ConnDataLen; + void *pContext; + int MaxPDUSize; + int MaxSDUSize; + int TTPCredits; + IRDA_SERVICE_STATUS ConnStatus; + BOOL UseTTP; +} IRDA_CONNECT_SERVICE; + +// IRDA Disconnection Service Request Message - IRLAP_DISCONNECT_REQ/IND +// IRLMP_DISCONNECT_REQ/IND +typedef enum +{ + IRLMP_USER_REQUEST = 1, + IRLMP_UNEXPECTED_IRLAP_DISC, + IRLMP_IRLAP_CONN_FAILED, + IRLMP_IRLAP_RESET, + IRLMP_LM_INITIATED_DISC, + IRLMP_DISC_LSAP, + IRLMP_NO_RESPONSE_LSAP, + IRLMP_NO_AVAILABLE_LSAP, + IRLMP_MAC_MEDIA_BUSY, + IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS, + + IRLMP_IAS_NO_SUCH_OBJECT, // these are added for the IAS_GetValueByClass.Conf + IRLMP_IAS_NO_SUCH_ATTRIB, + IRLMP_IAS_SUCCESS, + IRLMP_IAS_SUCCESS_LISTLEN_GREATER_THAN_ONE, + + IRLMP_UNSPECIFIED_DISC = 0xFF +} IRLMP_DISC_REASON; + +typedef struct +{ + BYTE *pDiscData; // IRLMP_DISCONNECT_REQ/IND only + int DiscDataLen; // IRLMP_DISCONNECT_REQ/IND only + IRLMP_DISC_REASON DiscReason; // IRLMP_DISCONNECT_REQ/IND only + IRDA_SERVICE_STATUS DiscStatus; // Indication only +} IRDA_DISCONNECT_SERVICE; + +// IRDA Data Service Request Message +#define IRLAP_HEADER_LEN 2 +#define IRLMP_HEADER_LEN 6 +#define TTP_HEADER_LEN 8 +#define IRDA_HEADER_LEN IRLAP_HEADER_LEN+IRLMP_HEADER_LEN+TTP_HEADER_LEN+1 + // + 1 IRComm WACK!! + +typedef struct +{ + void *pOwner; + void *pDataContext; // How IRDA gets user data + int SegCount; // Number of segments + BOOL FinalSeg; + BYTE *pBase; + BYTE *pLimit; + BYTE *pRead; + BYTE *pWrite; + void *pTdiSendComp; + void *pTdiSendCompCnxt; + BOOL IrCOMM_9Wire; +#ifdef TEMPERAMENTAL_SERIAL_DRIVER + int FCS; +#endif + IRDA_SERVICE_STATUS DataStatus; // for CONF + // |------------------------| + // | pRead o------------- + // |------------------------| | + // | pWrite o---------- | + // |------------------------| | | + // | pBase o------- | | + // |------------------------| | | | + // | pLimit o---- | | | + // |------------------------| | | | | + // | | | | | + // ------------------------ | | | | + // | |<---- | | + // | | | | | + // | |<--------<- + // | | | + // | |<- + // ------------------------ + BYTE *pHdrRead; + BYTE *pHdrWrite; + BYTE Header[IRDA_HEADER_LEN]; + // |------------------------| + // | pHdrRead o------------- + // |------------------------| | + // | pHdrWrite o---------- | + // |------------------------| | | + // Header--->| | | | + // | | | | + // | |<--------<- + // | | | + // | |<------- + // ------------------------ + // + // On the receive side, all headers are contained + // at pRead, not in the above Header array + // +} IRDA_DATA_SERVICE; + +typedef enum +{ + IRLMP_MULTIPLEXED, + IRLMP_EXCLUSIVE +} IRLMP_ACCESSMODE; + +typedef struct +{ + IRLMP_ACCESSMODE AccessMode; + IRDA_SERVICE_STATUS ModeStatus; + BOOL IrLPTMode; // if true don't send PDU +} IRLMP_ACCESSMODE_SERVICE; + +typedef struct +{ + IAS_QUERY *pIASQuery; + int AttribLen; // OctetSeq or UsrStr len + int IASQueryPerms; + IRLMP_DISC_REASON IASStatus; +} IRLMP_IAS_SERVICE; + +typedef struct irda_msg +{ + LIST_ENTRY Linkage; + IRDA_SERVICE_PRIM Prim; + union + { + MAC_CONTROL_SERVICE MAC_ControlService; + IRLAP_DISCOVERY_SERVICE IRLAP_DiscoveryService; + IRDA_DISCONNECT_SERVICE IRDA_DisconnectService; + IRDA_CONNECT_SERVICE IRDA_ConnectService; + IRDA_DATA_SERVICE IRDA_DataService; + IRLMP_ACCESSMODE_SERVICE IRLMP_AccessModeService; + IRLMP_IAS_SERVICE IRLMP_IASService; + } MsgType; + +} IRDA_MSG, *PIRDA_MSG; + +#define IRDA_MSG_Op MsgType.MAC_ControlService.Op +#define IRDA_MSG_Port MsgType.MAC_ControlService.Port +#define IRDA_MSG_Baud MsgType.MAC_ControlService.Baud +#define IRDA_MSG_NumBOFs MsgType.MAC_ControlService.NumBOFs +#define IRDA_MSG_MinTat MsgType.MAC_ControlService.MinTat +#define IRDA_MSG_DataSize MsgType.MAC_ControlService.DataSize +#define IRDA_MSG_OpStatus MsgType.MAC_ControlService.OpStatus +#define IRDA_MSG_SetIR MsgType.MAC_ControlService.SetIR +#define IRDA_MSG_SenseTime MsgType.MAC_ControlService.SenseTime + +#define IRDA_MSG_pOwner MsgType.IRDA_DataService.pOwner +#define IRDA_MSG_pDataContext MsgType.IRDA_DataService.pDataContext +#define IRDA_MSG_SegCount MsgType.IRDA_DataService.SegCount +#define IRDA_MSG_FinalSeg MsgType.IRDA_DataService.FinalSeg +#define IRDA_MSG_pHdrRead MsgType.IRDA_DataService.pHdrRead +#define IRDA_MSG_pHdrWrite MsgType.IRDA_DataService.pHdrWrite +#define IRDA_MSG_Header MsgType.IRDA_DataService.Header +#define IRDA_MSG_pBase MsgType.IRDA_DataService.pBase +#define IRDA_MSG_pLimit MsgType.IRDA_DataService.pLimit +#define IRDA_MSG_pRead MsgType.IRDA_DataService.pRead +#define IRDA_MSG_pWrite MsgType.IRDA_DataService.pWrite +#define IRDA_MSG_DataStatus MsgType.IRDA_DataService.DataStatus +#define IRDA_MSG_pTdiSendComp MsgType.IRDA_DataService.pTdiSendComp +#define IRDA_MSG_pTdiSendCompCnxt MsgType.IRDA_DataService.pTdiSendCompCnxt +#define IRDA_MSG_IrCOMM_9Wire MsgType.IRDA_DataService.IrCOMM_9Wire +#ifdef TEMPERAMENTAL_SERIAL_DRIVER +#define IRDA_MSG_FCS MsgType.IRDA_DataService.FCS +#endif + +#define IRDA_MSG_pDevList MsgType.IRLAP_DiscoveryService.pDevList +#define IRDA_MSG_DscvStatus MsgType.IRLAP_DiscoveryService.DscvStatus +#define IRDA_MSG_SenseMedia MsgType.IRLAP_DiscoveryService.SenseMedia + +#define IRDA_MSG_RemoteDevAddr MsgType.IRDA_ConnectService.RemoteDevAddr +#define IRDA_MSG_pQOS MsgType.IRDA_ConnectService.pQOS +#define IRDA_MSG_LocalLSAPSel MsgType.IRDA_ConnectService.LocalLSAPSel +#define IRDA_MSG_RemoteLSAPSel MsgType.IRDA_ConnectService.RemoteLSAPSel +#define IRDA_MSG_pConnData MsgType.IRDA_ConnectService.pConnData +#define IRDA_MSG_ConnDataLen MsgType.IRDA_ConnectService.ConnDataLen +#define IRDA_MSG_ConnStatus MsgType.IRDA_ConnectService.ConnStatus +#define IRDA_MSG_pContext MsgType.IRDA_ConnectService.pContext +#define IRDA_MSG_UseTTP MsgType.IRDA_ConnectService.UseTTP +#define IRDA_MSG_MaxSDUSize MsgType.IRDA_ConnectService.MaxSDUSize +#define IRDA_MSG_MaxPDUSize MsgType.IRDA_ConnectService.MaxPDUSize +#define IRDA_MSG_TTPCredits MsgType.IRDA_ConnectService.TTPCredits + +#define IRDA_MSG_pDiscData MsgType.IRDA_DisconnectService.pDiscData +#define IRDA_MSG_DiscDataLen MsgType.IRDA_DisconnectService.DiscDataLen +#define IRDA_MSG_DiscReason MsgType.IRDA_DisconnectService.DiscReason +#define IRDA_MSG_DiscStatus MsgType.IRDA_DisconnectService.DiscStatus + +#define IRDA_MSG_AccessMode MsgType.IRLMP_AccessModeService.AccessMode +#define IRDA_MSG_ModeStatus MsgType.IRLMP_AccessModeService.ModeStatus +#define IRDA_MSG_IrLPTMode MsgType.IRLMP_AccessModeService.IrLPTMode + +#define IRDA_MSG_pIASQuery MsgType.IRLMP_IASService.pIASQuery +#define IRDA_MSG_AttribLen MsgType.IRLMP_IASService.AttribLen +#define IRDA_MSG_IASQueryPerms MsgType.IRLMP_IASService.IASQueryPerms +#define IRDA_MSG_IASStatus MsgType.IRLMP_IASService.IASStatus + +extern LIST_ENTRY IrdaLinkCbList; + +VOID IrdaTimerInitialize(PIRDA_TIMER pTimer, + VOID (*ExpFunc)(PVOID Context), + UINT Timeout, + PVOID Context); + +VOID IrdaTimerStart(PIRDA_TIMER pTimer); + +VOID IrdaTimerStop(PIRDA_TIMER pTimer); + diff --git a/private/ntos/tdi/irda/inc/irdalink.h b/private/ntos/tdi/irda/inc/irdalink.h new file mode 100644 index 000000000..e96f13665 --- /dev/null +++ b/private/ntos/tdi/irda/inc/irdalink.h @@ -0,0 +1,34 @@ +NTSTATUS IrdaNdisInitialize(); + +#define IRDA_NDIS_BUFFER_POOL_SIZE 4 +#define IRDA_NDIS_PACKET_POOL_SIZE 4 +#define IRDA_MSG_LIST_LEN 2 +#define IRDA_MSG_DATA_SIZE 64 + +typedef struct +{ + PIRDA_MSG pIMsg; + MEDIA_SPECIFIC_INFORMATION MediaInfo; +} IRDA_PROTOCOL_RESERVED, *PIRDA_PROTOCOL_RESERVED; + +typedef struct IrdaLinkControlBlock +{ + LIST_ENTRY Linkage; + NDIS_SPIN_LOCK SpinLock; + NDIS_HANDLE BindContext; + NDIS_HANDLE NdisBindingHandle; + NDIS_EVENT SyncEvent; + NDIS_STATUS SyncStatus; + int MediaBusy; + PVOID IrlapContext; + PVOID IrlmpContext; + NDIS_HANDLE BufferPool; + NDIS_HANDLE PacketPool; + LIST_ENTRY IMsgList; + int IMsgListLen; + UINT ExtraBofs; // These should be per connection for + UINT MinTat; // multipoint +} IRDA_LINK_CB, *PIRDA_LINK_CB; + +IRDA_MSG *AllocMacIMsg(PIRDA_LINK_CB); + diff --git a/private/ntos/tdi/irda/inc/irerr.h b/private/ntos/tdi/irda/inc/irerr.h new file mode 100644 index 000000000..7490c6fba --- /dev/null +++ b/private/ntos/tdi/irda/inc/irerr.h @@ -0,0 +1,110 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irerr.h +* +* Description: IR error defines +* +* Author: mmiller +* +* Date: 4/25/95 +* +*/ + +#ifndef SUCCESS +#define SUCCESS 0 +#endif + +#define IR_ERROR_BASE 20000 +#define IRLAP_ERROR_BASE IR_ERROR_BASE + 100 +#define IRLMP_ERROR_BASE IR_ERROR_BASE + 200 + +#define IRMAC_TX_OVERFLOW (IR_ERROR_BASE+0) +#define IRMAC_WRITE_FAILED (IR_ERROR_BASE+1) +#define IRMAC_READ_FAILED (IR_ERROR_BASE+2) +#define IRMAC_BAD_FCS (IR_ERROR_BASE+3) +#define IRMAC_RX_OVERFLOW (IR_ERROR_BASE+4) +#define IRMAC_TIMEOUT (IR_ERROR_BASE+5) +#define IRMAC_BAD_PRIM (IR_ERROR_BASE+6) +#define IRMAC_BAD_OP (IR_ERROR_BASE+7) +#define IRMAC_OPEN_PORT_FAILED (IR_ERROR_BASE+8) +#define IRMAC_SET_BAUD_FAILED (IR_ERROR_BASE+9) +#define IRMAC_MALLOC_FAILED (IR_ERROR_BASE+10) +#define IRMAC_ALREADY_INIT (IR_ERROR_BASE+11) +#define IRMAC_BAD_TIMER (IR_ERROR_BASE+12) +#define IRMAC_NOT_INITIALIZED (IR_ERROR_BASE+13) +#define IRMAC_LINK_RESET (IR_ERROR_BASE+14) + +#define IRLAP_NOT_INITIALIZED (IRLAP_ERROR_BASE + 0) +#define IRLAP_BAD_PRIM (IRLAP_ERROR_BASE + 1) +#define IRLAP_BAD_STATE (IRLAP_ERROR_BASE + 2) +#define IRLAP_BAD_OPSTATUS (IRLAP_ERROR_BASE + 3) +#define IRLAP_BAD_OP (IRLAP_ERROR_BASE + 4) +#define IRLAP_MALLOC_FAILED (IRLAP_ERROR_BASE + 5) +#define IRLAP_BAUD_NEG_ERR (IRLAP_ERROR_BASE + 6) +#define IRLAP_DISC_NEG_ERR (IRLAP_ERROR_BASE + 7) +#define IRLAP_MAXTAT_NEG_ERR (IRLAP_ERROR_BASE + 8) +#define IRLAP_MINTAT_NEG_ERR (IRLAP_ERROR_BASE + 9) +#define IRLAP_DATASIZE_NEG_ERR (IRLAP_ERROR_BASE + 10) +#define IRLAP_WINSIZE_NEG_ERR (IRLAP_ERROR_BASE + 11) +#define IRLAP_BOFS_NEG_ERR (IRLAP_ERROR_BASE + 12) +#define IRLAP_LINECAP_ERR (IRLAP_ERROR_BASE + 13) +#define IRLAP_BAD_SLOTNO (IRLAP_ERROR_BASE + 14) +#define IRLAP_XID_CMD_NOT_P (IRLAP_ERROR_BASE + 15) +#define IRLAP_SNRM_NO_QOS (IRLAP_ERROR_BASE + 16) +#define IRLAP_UA_NO_QOS (IRLAP_ERROR_BASE + 17) +#define IRLAP_XID_CMD_RSP (IRLAP_ERROR_BASE + 18) +#define IRLAP_SNRM_NOT_CMD (IRLAP_ERROR_BASE + 19) +#define IRLAP_SNRM_NOT_P (IRLAP_ERROR_BASE + 20) +#define IRLAP_UA_NOT_RSP (IRLAP_ERROR_BASE + 21) +#define IRLAP_UA_NOT_F (IRLAP_ERROR_BASE + 22) +#define IRLAP_MSG_LIST_EMPTY (IRLAP_ERROR_BASE + 23) +#define IRLAP_MSG_LIST_FULL (IRLAP_ERROR_BASE + 24) +#define IRLAP_RXD_BAD_FRAME (IRLAP_ERROR_BASE + 25) +#define IRLAP_BAD_CRBIT_IFRAME (IRLAP_ERROR_BASE + 26) +#define IRLAP_BAD_DATA_REQUEST (IRLAP_ERROR_BASE + 27) +#define IRLAP_DISC_CMD_RSP (IRLAP_ERROR_BASE + 28) +#define IRLAP_DISC_CMD_NOT_P (IRLAP_ERROR_BASE + 29) +#define IRLAP_DM_RSP_NOT_F (IRLAP_ERROR_BASE + 30) +#define IRLAP_DM_RSP_CMD (IRLAP_ERROR_BASE + 31) +#define IRLAP_FRMR_RSP_CMD (IRLAP_ERROR_BASE + 32) +#define IRLAP_FRMR_RSP_NOT_F (IRLAP_ERROR_BASE + 33) +#define IRLAP_BAD_QOS (IRLAP_ERROR_BASE + 34) +#define IRLAP_NULL_MSG (IRLAP_ERROR_BASE + 35) +#define IRLAP_BAD_MAX_SLOT (IRLAP_ERROR_BASE + 36) +#define IRLAP_REMOTE_DISCOVERY_IN_PROGRESS_ERR (IRLAP_ERROR_BASE + 37) +#define IRLAP_REMOTE_CONNECTION_IN_PROGRESS_ERR (IRLAP_ERROR_BASE + 38) +#define IRLAP_REMOTE_BUSY (IRLAP_ERROR_BASE + 39) + +#define IRLMP_NOT_INITIALIZED (IRLMP_ERROR_BASE + 0) +#define IRLMP_LSAP_BAD_STATE (IRLMP_ERROR_BASE + 1) +#define IRLMP_USER_DATA_LEN_EXCEEDED (IRLMP_ERROR_BASE + 2) +#define IRLMP_LINK_IN_USE (IRLMP_ERROR_BASE + 3) +#define IRLMP_TIMER_START_FAILED (IRLMP_ERROR_BASE + 4) +#define IRLMP_ALLOC_FAILED (IRLMP_ERROR_BASE + 5) +#define IRLMP_LINK_BAD_STATE (IRLMP_ERROR_BASE + 6) +#define IRLMP_LSAP_SEL_IN_USE (IRLMP_ERROR_BASE + 7) +#define IRLMP_CREDIT_CALC_ERROR (IRLMP_ERROR_BASE + 8) +#define IRLMP_NO_TX_CREDIT (IRLMP_ERROR_BASE + 9) +#define IRLMP_TX_DATA_LEN_EXCEEDED (IRLMP_ERROR_BASE + 10) +#define IRLMP_DATA_IND_BAD_FRAME (IRLMP_ERROR_BASE + 11) +#define IRLMP_SCHEDULE_EVENT_FAILED (IRLMP_ERROR_BASE + 12) +#define IRLMP_LOCAL_BUSY (IRLMP_ERROR_BASE + 13) +#define IRLMP_BAD_PRIM (IRLMP_ERROR_BASE + 14) +#define IRLMP_BAD_ACCESSMODE (IRLMP_ERROR_BASE + 15) +#define IRLMP_LINK_BUSY (IRLMP_ERROR_BASE + 16) +#define IRLMP_IN_MULTIPLEXED_MODE (IRLMP_ERROR_BASE + 17) +#define IRLMP_IN_EXCLUSIVE_MODE (IRLMP_ERROR_BASE + 18) +#define IRLMP_NOT_LSAP_IN_EXCLUSIVE_MODE (IRLMP_ERROR_BASE + 19) +#define IRLMP_INVALID_LSAP_CB (IRLMP_ERROR_BASE + 20) +#define IRLMP_REMOTE_BUSY (IRLMP_ERROR_BASE + 21) +#define IRLMP_TIMER_STOP_FAILED (IRLMP_ERROR_BASE + 22) +#define IRLMP_BAD_IAS_OBJECT_ID (IRLMP_ERROR_BASE + 23) +#define IRLMP_NO_SUCH_IAS_CLASS (IRLMP_ERROR_BASE + 24) +#define IRLMP_NO_SUCH_IAS_ATTRIBUTE (IRLMP_ERROR_BASE + 25) +#define IRLMP_UNSUPPORTED_IAS_OPERATION (IRLMP_ERROR_BASE + 26) +#define IRLMP_BAD_IAS_QUERY_FROM_REMOTE (IRLMP_ERROR_BASE + 27) +#define IRLMP_IAS_QUERY_IN_PROGRESS (IRLMP_ERROR_BASE + 28) +#define IRLMP_UNSOLICITED_IAS_RESPONSE (IRLMP_ERROR_BASE + 29) +#define IRLMP_SHUTDOWN_IN_PROGESS (IRLMP_ERROR_BASE + 30) diff --git a/private/ntos/tdi/irda/inc/irlap.h b/private/ntos/tdi/irda/inc/irlap.h new file mode 100644 index 000000000..dbcc68361 --- /dev/null +++ b/private/ntos/tdi/irda/inc/irlap.h @@ -0,0 +1,66 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irlap.h +* +* Description: IRLAP Protocol and control block definitions +* +* Author: mbert +* +* Date: 4/15/95 +* +*/ + +// Sequence number modulus +#define IRLAP_MOD 8 +#define PV_TABLE_MAX_BIT 8 + +extern UINT vBaudTable[]; +extern UINT vMaxTATTable[]; +extern UINT vMinTATTable[]; +extern UINT vDataSizeTable[]; +extern UINT vWinSizeTable[]; +extern UINT vBOFSTable[]; +extern UINT vDiscTable[]; +extern UINT vThreshTable[]; +extern UINT vBOFSDivTable[]; + +VOID IrlapOpenLink( + OUT PNTSTATUS Status, + IN PIRDA_LINK_CB pIrdaLinkCb, + IN IRDA_QOS_PARMS *pQos, + IN BYTE *pDscvInfo, + IN int DscvInfoLen, + IN UINT MaxSlot); + +UINT IrlapDown(IN PVOID Context, + IN PIRDA_MSG); + +UINT IrlapUp(IN PVOID Context, + IN PIRDA_MSG); + +UINT IRLAP_Shutdown(); + +UINT IrlapGetQosParmVal(UINT[], UINT, UINT *); + +void IRLAP_PrintState(); + + + +typedef struct +{ + LIST_ENTRY ListHead; + int Len; +} IRDA_MSG_LIST; + +// I've exported these for the tester +UINT DequeMsgList(IRDA_MSG_LIST *, IRDA_MSG **); +UINT EnqueMsgList(IRDA_MSG_LIST *, IRDA_MSG *, int); +void InitMsgList(IRDA_MSG_LIST *); + + + + + + diff --git a/private/ntos/tdi/irda/inc/irlaplog.h b/private/ntos/tdi/irda/inc/irlaplog.h new file mode 100644 index 000000000..71f67866f --- /dev/null +++ b/private/ntos/tdi/irda/inc/irlaplog.h @@ -0,0 +1,44 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irlaplog.h +* +* Description: IRLAP state machine logging and errors +* +* Author: mbert +* +* Date: 4/15/95 +* +*/ + +#ifdef DEBUG + +extern TCHAR *IRDA_PrimStr[]; +extern TCHAR *IRLAP_StateStr[]; +extern TCHAR *MAC_OpStr[]; +extern TCHAR *IRDA_TimerStr[]; +extern TCHAR *IRDA_StatStr[]; + +#define SPRINT_BUF_LEN 1000 + +#define EXPAND_ADDR(Addr) (Addr[0], Addr[1], Addr[2], Addr[3]) + +void IRLAP_EventLogStart(PIRLAP_CB, TCHAR *pFormat, ...); +void __cdecl IRLAP_LogAction(PIRLAP_CB, TCHAR *pFormat, ...); +void IRLAP_EventLogComplete(PIRLAP_CB); +TCHAR *FrameToStr(IRDA_MSG *); + +#define IRLAP_LOG_START(X) IRLAP_EventLogStart X +#define IRLAP_LOG_ACTION(X) IRLAP_LogAction X +#define IRLAP_LOG_COMPLETE(X) IRLAP_EventLogComplete(X) + +#else + +#define IRLAP_LOG_START(X) (0) +#define IRLAP_LOG_ACTION(X) (0) +#define IRLAP_LOG_COMPLETE(X) (0) + +#endif + + diff --git a/private/ntos/tdi/irda/inc/irlmp.h b/private/ntos/tdi/irda/inc/irlmp.h new file mode 100644 index 000000000..ac46e4107 --- /dev/null +++ b/private/ntos/tdi/irda/inc/irlmp.h @@ -0,0 +1,60 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irlmp.h +* +* Description: IRLMP Protocol and control block definitions +* +* Author: mbert +* +* Date: 4/15/95 +* +*/ + +#define IRLMP_MAX_USER_DATA_LEN 53 + +// IrLMP Entry Points + +UINT IRLMP_Initialize(int Port, BOOL SetIR, BYTE DscvInfo[], int DscvInfoLen, + IRDA_QOS_PARMS *pQOS, int MaxSlot, CHAR *pDeviceName, + int DeviceNameLen); + +UINT IrlmpDown(PVOID IrlmpContext, PIRDA_MSG pIMsg); +UINT IrlmpUp(PVOID IrlmpContext, PIRDA_MSG pIMsg); + +UINT IRLMP_RegisterLSAPProtocol(int LSAP, BOOL UseTTP); +UINT IRLMP_Shutdown(); + +#ifdef DEBUG +void IRLMP_PrintState(); +#endif + +// IAS + +#define IAS_ASCII_CHAR_SET 0 + +// IAS Attribute value types +#define IAS_ATTRIB_VAL_MISSING 0 +#define IAS_ATTRIB_VAL_INTEGER 1 +#define IAS_ATTRIB_VAL_BINARY 2 +#define IAS_ATTRIB_VAL_STRING 3 + +// IAS Operation codes +#define IAS_OPCODE_GET_VALUE_BY_CLASS 4 // The only one I do + +extern const CHAR IAS_ClassName_Device[]; +extern const CHAR IAS_AttribName_DeviceName[]; +extern const CHAR IAS_AttribName_IrLMPSupport[]; +extern const CHAR IAS_AttribName_TTPLsapSel[]; +extern const CHAR IAS_AttribName_IrLMPLsapSel[]; + +extern const BYTE IAS_ClassNameLen_Device; +extern const BYTE IAS_AttribNameLen_DeviceName; +extern const BYTE IAS_AttribNameLen_IRLMPSupport; +extern const BYTE IAS_AttribNameLen_TTPLsapSel; +extern const BYTE IAS_AttribNameLen_IrLMPLsapSel; + +UINT IAS_AddAttribute(IAS_SET *pIASSet); + +UINT IAS_DeleteObject(CHAR *pClassName); diff --git a/private/ntos/tdi/irda/inc/irmac.h b/private/ntos/tdi/irda/inc/irmac.h new file mode 100644 index 000000000..534e83525 --- /dev/null +++ b/private/ntos/tdi/irda/inc/irmac.h @@ -0,0 +1,32 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irmac.h +* +* Description: IRLAP MAC definitions and entry point prototypes +* +* Author: mbert +* +* Date: 4/15/95 +* +*/ + +// Entry Points + +UINT IrmacInitialize(); + +UINT IrmacDown( + IN PVOID IrmacContext, + PIRDA_MSG pMsg); + +UINT IRMAC_RxFrame(IRDA_MSG *pMsg); +UINT IRMAC_TimerExpired(IRDA_TIMER Timer); +void IRMAC_PrintState(); + + + + + + + diff --git a/private/ntos/tdi/irda/inc/oscfg.h b/private/ntos/tdi/irda/inc/oscfg.h new file mode 100644 index 000000000..49eab5e00 --- /dev/null +++ b/private/ntos/tdi/irda/inc/oscfg.h @@ -0,0 +1,62 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: oscfg.h +* +* Description: OS configuration section +* +* Author: mmiller +* +* Date: 4/25/95 +* +*/ +#ifdef PEG + +// Pegasus specific includes/defines +#include "peg.h" + +#define DbgPrint NKDbgPrintfW + +#else // PEG + +#include +//#include +//#include +//#include + +//#include +//#include +//#include + +#define RETAILMSG(exp,p) (0) +#define DEBUGMSG(exp,p) (0) + +// NT specific includes/defines +//#include "windows.h" +//#include "stdio.h" + +//#define DbgPrint printf +//typedef char TCHAR; + +//#define RETAILMSG(exp,p) ((exp)?DbgPrint p,1:0) + +//#ifdef DEBUG + +//#define DEBUGMSG(exp,p) ((exp)?DbgPrint p,1:0) +//#undef NDEBUG + +//#define DEBUGZONE(x) 1<| | +* | IRLAP | | TIMER | +* | |<--------------------------| | +* |---------| IRLAP_TimerExp() |-------| +* /|\ | +* | | +* IrlapUp() | |IrmacDown() +* IRLAP_GetRxMsg() | | +* | \|/ +* |---------| +* | 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 +#include +#include +#include +#include +#include +#include +#include + + +#ifdef TEMPERAMENTAL_SERIAL_DRIVER +int TossedDups; +#endif + +STATIC UINT _rc; // return code +STATIC IRDA_MSG IMsg; // for locally generated messages to LMP/MAC +STATIC UINT IRLAP_SlotTable[] = {1, 6, 8, 16}; +STATIC IRLAP_FRMR_FORMAT FrmRejFormat; + +BYTE IRLAP_BroadcastDevAddr[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,0, 0, 4000000}; +UINT vMaxTATTable[] = {500, 250, 100, 50, 25, 10, 5, 0, 0 }; +UINT vMinTATTable[] = {10000,5000, 1000, 500, 100, 50, 10,0, 0 }; +UINT vDataSizeTable[] = {64, 128, 256, 512, 1024, 2048, 0, 0, 0 }; +UINT vWinSizeTable[] = {1, 2, 3, 4, 5, 6, 7, 0, 0 }; +UINT vBOFSTable[] = {48, 24, 12, 5, 3, 2, 1, 0, 0 }; +UINT vDiscTable[] = {3, 8, 12, 16, 20, 25, 30,40,0 }; +UINT vThreshTable[] = {0, 3, 3, 3, 3, 3, 3, 3, 0 }; +UINT vBOFSDivTable[] = {48, 12, 6, 3, 2, 1, 1, 1, 0 }; + +// Tables for determining number of BOFS for baud and min turn time +// min turn time - 10ms 5ms 1ms 0.5ms 0.1ms 0.05ms 0.01ms +// ------------------------------------------------------------- +UINT BOFS_9600[] = {10, 5, 1, 0, 0, 0, 0}; +UINT BOFS_19200[] = {20, 10, 2, 1, 0, 0, 0}; +UINT BOFS_38400[] = {40, 20, 4, 2, 0, 0, 0}; +UINT BOFS_57600[] = {58, 29, 6, 3, 1, 0, 0}; +UINT BOFS_115200[] = {115, 58, 12, 6, 1, 1, 0}; + +// 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}; +UINT MAXCAP_19200[] = {800, 400, 160, 0, 0, 0, 0}; +UINT MAXCAP_38400[] = {1600, 800, 320, 0, 0, 0, 0}; +UINT MAXCAP_57600[] = {2360, 1180, 472, 0, 0, 0, 0}; +UINT MAXCAP_115200[] = {4800, 2400, 960, 480, 240, 96, 48}; + +// prototypes +STATIC UINT InitializeState(PIRLAP_CB, IRLAP_STN_TYPE); +STATIC UINT ReturnTxMsgs(PIRLAP_CB); +STATIC UINT ProcessConnectReq(PIRLAP_CB, PIRDA_MSG); +STATIC UINT ProcessConnectResp(PIRLAP_CB, PIRDA_MSG); +STATIC UINT ProcessDiscoveryReq(PIRLAP_CB, PIRDA_MSG); +STATIC UINT ProcessDisconnectReq(PIRLAP_CB); +STATIC UINT ProcessDataAndUDataReq(PIRLAP_CB, PIRDA_MSG); +STATIC UINT XmitTxMsgList(PIRLAP_CB, BOOL, BOOL *); +STATIC UINT GotoPCloseState(PIRLAP_CB); +STATIC UINT GotoNDMThenDscvOrConn(PIRLAP_CB); +STATIC UINT ProcessMACControlConf(PIRLAP_CB, PIRDA_MSG); +STATIC UINT ProcessMACDataInd(PIRLAP_CB, PIRDA_MSG , BOOL *); +STATIC UINT ProcessDscvXIDCmd(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, BYTE *); +STATIC UINT ProcessDscvXIDRsp(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, BYTE *); +STATIC void ExtractQosParms(IRDA_QOS_PARMS *, BYTE *, BYTE *); +STATIC UINT InitDscvCmdProcessing(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *); +STATIC void ExtractDeviceInfo(IRDA_DEVICE *, IRLAP_XID_DSCV_FORMAT *, BYTE *); +STATIC BOOL DevInDevList(BYTE[], LIST_ENTRY *); +STATIC UINT AddDevToList(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, BYTE *); +STATIC void ClearDevList(LIST_ENTRY *); +STATIC UINT ProcessSNRM(PIRLAP_CB, IRLAP_SNRM_FORMAT *, BYTE *); +STATIC UINT ProcessUA(PIRLAP_CB, IRLAP_UA_FORMAT *, BYTE *); +STATIC UINT ProcessDISC(PIRLAP_CB); +STATIC UINT ProcessRD(PIRLAP_CB); +STATIC UINT ProcessRNRM(PIRLAP_CB); +STATIC UINT ProcessDM(PIRLAP_CB); +STATIC UINT ProcessFRMR(PIRLAP_CB); +STATIC UINT ProcessTEST(PIRLAP_CB, PIRDA_MSG, IRLAP_UA_FORMAT *, int, int); +STATIC UINT ProcessUI(PIRLAP_CB, PIRDA_MSG, int, int); +STATIC UINT ProcessREJ_SREJ(PIRLAP_CB, int, PIRDA_MSG, int, int, UINT); +STATIC UINT ProcessRR_RNR(PIRLAP_CB, int, PIRDA_MSG, int, int, UINT); +STATIC UINT ProcessIFrame(PIRLAP_CB, PIRDA_MSG, int, int, UINT, UINT, BOOL *); +STATIC BOOL InvalidNsOrNr(PIRLAP_CB, UINT, UINT); +STATIC BOOL InvalidNr(PIRLAP_CB, UINT); +STATIC BOOL InWindow(UINT, UINT, UINT); +STATIC UINT ProcessInvalidNsOrNr(PIRLAP_CB, int); +STATIC UINT ProcessInvalidNr(PIRLAP_CB, int); +STATIC UINT InsertRxWinAndForward(PIRLAP_CB, PIRDA_MSG, UINT, BOOL *); +STATIC UINT ResendRejects(PIRLAP_CB, UINT); +STATIC UINT FreeAckedTxMsgs(PIRLAP_CB, UINT); +STATIC UINT MissingRxFrames(PIRLAP_CB); +STATIC UINT IFrameOtherStates(PIRLAP_CB, int, int); +STATIC UINT NegotiateQosParms(PIRLAP_CB, IRDA_QOS_PARMS *); +STATIC UINT ApplyQosParms(PIRLAP_CB); +STATIC UINT StationConflict(PIRLAP_CB); +STATIC UINT ApplyDefaultParms(PIRLAP_CB); +STATIC UINT ResendDISC(PIRLAP_CB); +STATIC BOOL IgnoreState(PIRLAP_CB); +STATIC BOOL MyDevAddr(PIRLAP_CB, BYTE []); +STATIC VOID SlotTimerExp(PVOID); +STATIC VOID FinalTimerExp(PVOID); +STATIC VOID PollTimerExp(PVOID); +STATIC VOID BackoffTimerExp(PVOID); +STATIC VOID WDogTimerExp(PVOID); +STATIC VOID QueryTimerExp(PVOID); + +#ifdef DEBUG +void _inline IRLAP_TimerStart(PIRLAP_CB pIrlapCb, PIRDA_TIMER pTmr) +{ + IRLAP_LOG_ACTION((pIrlapCb, "Start %s timer for %dms", pTmr->pName, + pTmr->Timeout)); + IrdaTimerStart(pTmr); +} + +void _inline IRLAP_TimerStop(PIRLAP_CB pIrlapCb, PIRDA_TIMER pTmr) +{ + IRLAP_LOG_ACTION((pIrlapCb, "Stop %s timer", pTmr->pName)); + IrdaTimerStop(pTmr); +} +#else +#define IRLAP_TimerStart(c,t) IrdaTimerStart(t) +#define IRLAP_TimerStop(c,t) IrdaTimerStop(t) +#endif + +VOID +IrlapOpenLink(OUT PNTSTATUS Status, + IN PIRDA_LINK_CB pIrdaLinkCb, + IN IRDA_QOS_PARMS *pQos, + IN BYTE *pDscvInfo, + IN int DscvInfoLen, + IN UINT MaxSlot) +{ + UINT rc = SUCCESS; + int i; + IRDA_MSG *pMsg; + PIRLAP_CB pIrlapCb; + + DEBUGMSG(DBG_IRLAP, ("IrlapOpenLink\n")); + + if ((pIrlapCb = CTEAllocMem(sizeof(IRLAP_CB))) == NULL) + { + DEBUGMSG(DBG_ERROR, ("Alloc failed\n")); + *Status = STATUS_INSUFFICIENT_RESOURCES; + return; + } + + pIrdaLinkCb->IrlapContext = pIrlapCb; + + DscvInfoLen = DscvInfoLen > IRLAP_DSCV_INFO_LEN ? + IRLAP_DSCV_INFO_LEN : DscvInfoLen; + + memcpy(pIrlapCb->LocalDevice.DscvInfo, pDscvInfo, DscvInfoLen); + + pIrlapCb->LocalDevice.DscvInfoLen = DscvInfoLen; + + memcpy(&pIrlapCb->LocalQos, pQos, sizeof(IRDA_QOS_PARMS)); + + pIrlapCb->Sig = IRLAP_CB_SIG; + 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*/; + } + + // initialize as PRIMARY so UI frames in contention + // state sends CRBit = cmd + if ((rc = InitializeState(pIrlapCb, PRIMARY)) != SUCCESS) + { + CTEFreeMem(pIrlapCb); + *Status = STATUS_UNSUCCESSFUL; + return; + } + + pIrlapCb->State = NDM; + + // Generate random local address + StoreULAddr(pIrlapCb->LocalDevice.DevAddr, (ULONG) GetMyDevAddr(FALSE)); + + pIrlapCb->LocalDevice.IRLAP_Version = 1; + + pIrlapCb->Baud = IRLAP_DEFAULT_BAUD; + pIrlapCb->RemoteMaxTAT = IRLAP_DEFAULT_MAX_TAT; + pIrlapCb->RemoteDataSize = IRLAP_DEFAULT_DATA_SIZE; + pIrlapCb->RemoteWinSize = IRLAP_DEFAULT_WIN_SIZE; + pIrlapCb->RemoteNumBOFS = IRLAP_DEFAULT_BOFS; + + pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR; + + pIrlapCb->N1 = 0; // calculated at negotiation + pIrlapCb->N2 = 0; + pIrlapCb->N3 = 5; // recalculated after negotiation ?? + +#ifdef DEBUG + 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); + + IrdaTimerInitialize(&pIrlapCb->FinalTimer, + FinalTimerExp, + pIrlapCb->LocalMaxTAT, + pIrlapCb); + + IrdaTimerInitialize(&pIrlapCb->SlotTimer, + SlotTimerExp, + IRLAP_SLOT_TIMEOUT, + pIrlapCb); + + IrdaTimerInitialize(&pIrlapCb->QueryTimer, + QueryTimerExp, + (IRLAP_MAX_SLOTS + 4) * IRLAP_SLOT_TIMEOUT*2, + pIrlapCb); + + IrdaTimerInitialize(&pIrlapCb->WDogTimer, + WDogTimerExp, + 3000, + pIrlapCb); + + IrdaTimerInitialize(&pIrlapCb->BackoffTimer, + BackoffTimerExp, + 0, + pIrlapCb); + + // Initialize Link + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_INITIALIZE_LINK; + IMsg.IRDA_MSG_Baud = IRLAP_DEFAULT_BAUD; + IMsg.IRDA_MSG_NumBOFs = IRLAP_DEFAULT_BOFS; + IMsg.IRDA_MSG_DataSize = IRLAP_DEFAULT_DATA_SIZE; + IMsg.IRDA_MSG_MinTat = 0; + + rc = IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg); + + *Status = rc; + return; +} + + +VOID +IrlapCloseLink(PIRLAP_CB pIrlapCb) +{ + return; +} + +/***************************************************************************** +* +* @func UINT | InitializeState | resets link control block +* +* @parm IRLAP_STN_TYPE | StationType| sets station type and the CRBit +* in the control block +*/ +UINT +InitializeState(PIRLAP_CB pIrlapCb, + IRLAP_STN_TYPE StationType) +{ + int i; + + pIrlapCb->StationType = StationType; + + if (StationType == PRIMARY) + pIrlapCb->CRBit = IRLAP_CMD; + else + pIrlapCb->CRBit = IRLAP_RSP; + + pIrlapCb->RemoteBusy = FALSE; + pIrlapCb->LocalBusy = FALSE; + pIrlapCb->ClrLocalBusy = FALSE; + pIrlapCb->NoResponse = FALSE; + pIrlapCb->LocalDiscReq = FALSE; + pIrlapCb->ConnAfterClose = FALSE; + pIrlapCb->DscvAfterClose = FALSE; + pIrlapCb->GenNewAddr = FALSE; + pIrlapCb->StatusSent = FALSE; + pIrlapCb->Vs = 0; + pIrlapCb->Vr = 0; + pIrlapCb->WDogExpCnt = 0; + + ClearDevList(&pIrlapCb->DevList); + + memset(&pIrlapCb->RemoteQos, 0, sizeof(IRDA_QOS_PARMS)); + memset(&pIrlapCb->NegotiatedQos, 0, sizeof(IRDA_QOS_PARMS)); + + // Return msgs on tx list and in tx window + RetOnErr(ReturnTxMsgs(pIrlapCb)); + + // Cleanup RxWin + pIrlapCb->RxWin.Start = 0; + pIrlapCb->RxWin.End = 0; + for (i = 0; i < IRLAP_MOD; i++) + { + // Receive window + if (pIrlapCb->RxWin.pMsg[i] != NULL) + { + /* RETURN THESE BACK TO NDIS + RetOnErr(EnqueMsgList(&pIrlapCb->RxMsgFreeList, + pIrlapCb->RxWin.pMsg[i], + pIrlapCb->MaxRxMsgFreeListLen)); + */ + pIrlapCb->RxWin.pMsg[i] = NULL; + } + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc return desc +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +*/ +/* +UINT +IRLAP_Shutdown() +{ + UINT rc = SUCCESS; + + IRLAP_LOG_START(pIrlapCb, (TEXT("IRLAP Shutdown"))); + + if ((rc = ReturnTxMsgs(pIrlapCb)) == SUCCESS) + { + // Shutdown Link + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_SHUTDOWN_LINK; + rc = IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg); + } + if (pIrlapCb->pRxMsgOut != NULL) + { + IRDA_FREE_MEM(pIrlapCb->pRxMsgOut); + } + + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->SlotTimer); + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->QueryTimer); + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->PollTimer); + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->BackoffTimer); + IRLAP_TimerStop(pIrlapCb, IRMAC_MediaSenseTimer); + + IRLAP_LOG_COMPLETE(pIrlapCb); + + return rc; +} +*/ +/***************************************************************************** +* +* @func UINT | IrlapDown | Entry point into IRLAP for LMP +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag IRLAP_BAD_PRIMITIVE | Received message that didn't contain one +* of the primitives defined below +* IRLAP_NOT_INITIALIZED | IRLAP has not been intialize with +* IrlapInitialize() +* +* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message +* +* @comm Processes the following service requests: +* IRLAP_DISCOVERY_REQ, +* IRLAP_CONNECT_REQ, +* IRLAP_CONNECT_RESP, +* IRLAP_DISCONNECT_REQ, +* IRLAP_DATA_REQ, +* IRLAP_UDATA_REQ, +*/ +UINT +IrlapDown(PVOID Context, + PIRDA_MSG pMsg) +{ + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + UINT rc = SUCCESS; + + IRLAP_LOG_START((pIrlapCb, IRDA_PrimStr[pMsg->Prim])); + + switch (pMsg->Prim) + { + case IRLAP_DISCOVERY_REQ: + rc = ProcessDiscoveryReq(pIrlapCb, pMsg); + break; + + case IRLAP_CONNECT_REQ: + rc = ProcessConnectReq(pIrlapCb, pMsg); + break; + + case IRLAP_CONNECT_RESP: + rc = ProcessConnectResp(pIrlapCb, pMsg); + break; + + case IRLAP_DISCONNECT_REQ: + rc = ProcessDisconnectReq(pIrlapCb); + break; + + case IRLAP_DATA_REQ: + case IRLAP_UDATA_REQ: + rc = ProcessDataAndUDataReq(pIrlapCb, pMsg); + break; + + case IRLAP_FLOWON_REQ: + if (pIrlapCb->LocalBusy) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Local busy condition cleared"))); + pIrlapCb->LocalBusy = FALSE; + pIrlapCb->ClrLocalBusy = TRUE; + } + break; + + default: + rc = IRLAP_BAD_PRIM; + + } + + IRLAP_LOG_COMPLETE(pIrlapCb); + + return (rc); +} +/***************************************************************************** +* +* @func UINT | IrlapUp | Entry point into IRLAP for MAC +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag IRLAP_BAD_PRIMITIVE | Received message that didn't contain one +* of the primitives defined below +* IRLAP_NOT_INITIALIZED | IRLAP has not been intialize with +* IrlapInitialize() +* +* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message +* +* @comm Processes the following service requests: +* MAC_DATA_IND +* MAC_CONTROL_CONF +*/ +UINT +IrlapUp(PVOID Context, PIRDA_MSG pMsg) +{ + UINT rc = SUCCESS; + BOOL FreeMsg = TRUE; + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + + // Whats this again ??? !!! pIrlapCb->pRxMsgOut = NULL; + + ASSERT(pIrlapCb->Sig == IRLAP_CB_SIG); + + switch (pMsg->Prim) + { + case MAC_DATA_IND: +// IRLAP_LOG_START((pIrlapCb, TEXT("MAC_DATA_IND: %s"), FrameToStr(pMsg))); + IRLAP_LOG_START((pIrlapCb, TEXT("MAC_DATA_IND"))); + + rc = ProcessMACDataInd(pIrlapCb, pMsg, &FreeMsg); + + /* What dis all about? + if (FreeMsg && SUCCESS == rc) + { + rc = EnqueMsgList(&pIrlapCb->RxMsgFreeList, pMsg, + pIrlapCb->MaxRxMsgFreeListLen); + } + */ + break; + + case MAC_CONTROL_CONF: + IRLAP_LOG_START((pIrlapCb, IRDA_PrimStr[pMsg->Prim])); + rc = ProcessMACControlConf(pIrlapCb, pMsg); + break; + + default: + IRLAP_LOG_START((pIrlapCb, IRDA_PrimStr[pMsg->Prim])); + rc = IRLAP_BAD_PRIM; + + } + + IRLAP_LOG_COMPLETE(pIrlapCb); + + return (rc); +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc return desc +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ + +/* THIS FUCKER GOES +UINT +IRLAP_GetRxMsg(IRDA_MSG **ppMsg) +{ + UINT rc = SUCCESS; + + ASSERT(pIrlapCb->pRxMsgOut == NULL); + + if ((rc = DequeMsgList(&pIrlapCb->RxMsgFreeList, ppMsg)) == SUCCESS) + { + (*ppMsg)->IRDA_MSG_pBase = ((BYTE *) (*ppMsg)) + sizeof(IRDA_MSG); + (*ppMsg)->IRDA_MSG_pLimit = ((BYTE *) (*ppMsg)) + + sizeof(IRDA_MSG)+ 5 + pIrlapCb->LocalDataSize; + + pIrlapCb->pRxMsgOut = *ppMsg; + } + + return rc; +} +*/ + +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ReturnTxMsgs(PIRLAP_CB pIrlapCb) +{ + int i; + IRDA_MSG *pMsg; + + // Return messages on TxMsgList to LMP + while (DequeMsgList(&pIrlapCb->TxMsgList, &pMsg) == SUCCESS) + { + pMsg->Prim += 2; // make it a confirm + pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_FAILED_LINK_RESET; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg)); + } + + pIrlapCb->TxWin.Start = 0; + pIrlapCb->TxWin.End = 0; + // Transmit window + for (i = 0; i < IRLAP_MOD; i++) + { + if (pIrlapCb->TxWin.pMsg[i] != NULL) + { + pIrlapCb->TxWin.pMsg[i]->Prim = IRLAP_DATA_CONF; + pIrlapCb->TxWin.pMsg[i]->IRDA_MSG_DataStatus = + IRLAP_DATA_REQUEST_FAILED_LINK_RESET; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, pIrlapCb->TxWin.pMsg[i])); + + pIrlapCb->TxWin.pMsg[i] = NULL; + } + } + + return SUCCESS; +} + +/***************************************************************************** +* +* @func BOOL | MyDevAddr | Determines if DevAddr matches the local +* device address or is the broadcast +* +* @rdesc TRUE if address is mine or broadcast else FALS +* +* @parm BYTE [] | DevAddr | Device Address +* +*/ +BOOL +MyDevAddr(PIRLAP_CB pIrlapCb, + BYTE DevAddr[]) +{ + if (memcmp(DevAddr, IRLAP_BroadcastDevAddr, IRDA_DEV_ADDR_LEN) != 0 && + memcmp(DevAddr, pIrlapCb->LocalDevice.DevAddr, IRDA_DEV_ADDR_LEN) != 0) + { + return FALSE; + } + return TRUE; +} + +/***************************************************************************** +* +* @func UINT | ProcessConnectReq | Process connect request from LMP +* +* @rdesc 0, otherwise one of the following errors: +* @flag IRLAP_BAD_STATE | Requested connection in an invalid state +* +* @parm IRDA_MSG * | pMsg | pointer to an IRDA_MSG +* +* @comm +* comments +*/ +UINT +ProcessConnectReq(PIRLAP_CB pIrlapCb, + PIRDA_MSG pMsg) +{ + switch (pIrlapCb->State) + { + case NDM: + // Save Remote Address for later use + memcpy(pIrlapCb->RemoteDevice.DevAddr, pMsg->IRDA_MSG_RemoteDevAddr, + IRDA_DEV_ADDR_LEN); + + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE; + IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME; + + RetOnErr(IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg)); + pIrlapCb->State = CONN_MEDIA_SENSE; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (media sense)"))); + break; + + case DSCV_REPLY: + return IRLAP_REMOTE_DISCOVERY_IN_PROGRESS_ERR; + + case P_CLOSE: + memcpy(pIrlapCb->RemoteDevice.DevAddr, + pMsg->IRDA_MSG_RemoteDevAddr, IRDA_DEV_ADDR_LEN); + pIrlapCb->ConnAfterClose = TRUE; + break; + + default: + return IRLAP_BAD_STATE; + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessConnectResp | Process connect response from LMP +* +* @rdesc 0, otherwise one of the following errors: +* @flag IRLAP_BAD_STATE | Requested connection in an invalid state +* +* @parm IRDA_MSG * | pMsg | pointer to an IRDA_MSG +* +* @comm +* comments +*/ +UINT +ProcessConnectResp(PIRLAP_CB pIrlapCb, + PIRDA_MSG pMsg) +{ + + if (pIrlapCb->State != SNRM_RECEIVED) + { + return IRLAP_BAD_STATE; + } + + pIrlapCb->ConnAddr = pIrlapCb->SNRMConnAddr; + RetOnErr(SendUA(pIrlapCb, TRUE)); + RetOnErr(ApplyQosParms(pIrlapCb)); + + RetOnErr(InitializeState(pIrlapCb, SECONDARY)); + // start watchdog timer with poll timeout + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + pIrlapCb->State = S_NRM; + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessDiscoveryReq | Process Discovery request from LMP +* +* @rdesc 0, otherwise one of the following errors: +* @flag IRLAP_BAD_STATE | Requested discovery in an invalid state +* +* @comm +* comments +*/ +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; + RetOnErr(IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg)); + pIrlapCb->State = DSCV_MEDIA_SENSE; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (media sense)"))); + } + else + { + pIrlapCb->SlotCnt = 0; + pIrlapCb->GenNewAddr = FALSE; + + ClearDevList(&pIrlapCb->DevList); + + RetOnErr(SendDscvXIDCmd(pIrlapCb)); + + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE; + IMsg.IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (dscv sense)"))); + RetOnErr(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: + return IRLAP_BAD_STATE; + } + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessDisconnectReq | Process disconnect request from LMP +* +* @rdesc 0, otherwise one of the following errors: +* @flag IRLAP_BAD_STATE | Requested disconnect in an invalid state +* +* @comm +* comments +*/ +UINT +ProcessDisconnectReq(PIRLAP_CB pIrlapCb) +{ + RetOnErr(ReturnTxMsgs(pIrlapCb)); + + switch (pIrlapCb->State) + { + case NDM: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + break; + + case SNRM_SENT: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + case DSCV_MEDIA_SENSE: + case DSCV_QUERY: + case DSCV_REPLY: + case CONN_MEDIA_SENSE: + pIrlapCb->State = NDM; + break; + + case BACKOFF_WAIT: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->BackoffTimer); + pIrlapCb->State = NDM; + break; + + case SNRM_RECEIVED: + pIrlapCb->ConnAddr = pIrlapCb->SNRMConnAddr; + RetOnErr(SendDM(pIrlapCb)); + pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR; + pIrlapCb->State = NDM; + break; + + case P_XMIT: + pIrlapCb->LocalDiscReq = TRUE; + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->PollTimer); + RetOnErr(SendDISC(pIrlapCb)); + IRLAP_TimerStart(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: + return IRLAP_BAD_STATE; + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessDataReq | Process data request from LMP +* +* @rdesc 0, otherwise one of the following errors: +* @flag IRLAP_BAD_STATE | Requested data in an invalid state +* @flag IRLAP_TX_MSG_LIST_FULL | Tx Msg List has become full, can't process +* +* @comm +* comments +*/ +UINT +ProcessDataAndUDataReq(PIRLAP_CB pIrlapCb, + PIRDA_MSG pMsg) +{ + BOOL LinkTurned; + int DataSize = (pMsg->IRDA_MSG_pHdrWrite - pMsg->IRDA_MSG_pHdrRead) + + (pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead); + + if (DataSize > pIrlapCb->RemoteDataSize) + { + return IRLAP_BAD_DATA_REQUEST; + } + + 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 + RetOnErr(EnqueMsgList(&pIrlapCb->TxMsgList, pMsg, -1)); + + RetOnErr(XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned)); + + if (LinkTurned) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->PollTimer); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + pIrlapCb->State = P_RECV; + } + return SUCCESS; + + case P_DISCONNECT_PEND: // For pending disconnect states, take the message. + case S_DISCONNECT_PEND: // They will be returned when the link disconnects + case P_RECV: + case S_NRM: + // Que the message for later transmission + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Queueing request"))); + + RetOnErr(EnqueMsgList(&pIrlapCb->TxMsgList, pMsg, -1)); + + return SUCCESS; + + default: + if (pMsg->Prim == IRLAP_DATA_REQ) + { + return IRLAP_BAD_STATE; + } + else + { + if (pIrlapCb->State == NDM) + { + return SendUIFrame(pIrlapCb, pMsg); + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + } + } + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +XmitTxMsgList(PIRLAP_CB pIrlapCb, BOOL AlwaysTurnLink, BOOL *pLinkTurned) +{ + UINT rc = SUCCESS; + 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 ((rc == SUCCESS) && !LinkTurned && + (DequeMsgList(&pIrlapCb->TxMsgList, &pMsg) == SUCCESS)) + { + if (pMsg->Prim == IRLAP_DATA_REQ) + { + // Insert message into transmit window + pIrlapCb->TxWin.pMsg[pIrlapCb->Vs] = pMsg; + + // 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*/)) + { + rc = SendIFrame(pIrlapCb, + pMsg, + pIrlapCb->Vs, + IRLAP_PFBIT_SET); + LinkTurned = TRUE; + } + else + { + rc = SendIFrame(pIrlapCb, + pMsg, + pIrlapCb->Vs, + IRLAP_PFBIT_CLEAR); + } + pIrlapCb->Vs = (pIrlapCb->Vs + 1) % IRLAP_MOD; + } + else // IRLAP_UDATA_REQUEST + { + // For now, always turn link + rc = SendUIFrame(pIrlapCb, pMsg); + pMsg->Prim = IRLAP_UDATA_CONF; + pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_COMPLETED; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg)); + LinkTurned = TRUE; + } + } + pIrlapCb->TxWin.End = pIrlapCb->Vs; + } + + if (rc == SUCCESS) + { + if ((AlwaysTurnLink && !LinkTurned) || pIrlapCb->ClrLocalBusy) + { + rc = SendRR_RNR(pIrlapCb); + LinkTurned = TRUE; + if (pIrlapCb->ClrLocalBusy) + { + pIrlapCb->ClrLocalBusy = FALSE; + } + } + } + + if (pLinkTurned != NULL) + { + *pLinkTurned = LinkTurned; + } + + return (rc); +} + +UINT +GotoPCloseState(PIRLAP_CB pIrlapCb) +{ + if (!pIrlapCb->LocalDiscReq) + { + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_REMOTE_INITIATED; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + } + + pIrlapCb->State = P_CLOSE; + + return SUCCESS; +} + +UINT +GotoNDMThenDscvOrConn(PIRLAP_CB pIrlapCb) +{ + 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; + + RetOnErr(IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg)); + pIrlapCb->State = CONN_MEDIA_SENSE; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (media sense)"))); + + return SUCCESS; + } + + 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; + RetOnErr(IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg)); + pIrlapCb->State = DSCV_MEDIA_SENSE; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (media sense)"))); + return SUCCESS; + } + pIrlapCb->State = NDM; + return SUCCESS; +} + +/***************************************************************************** +* +* @func UINT | ProcessMACControlConf | Process a control confirm from MAC +* +* @rdesc SUCCESS, otherwise one of the following error codes +* @flag IRLAP_BAD_OP | Bad Operation, must be MAC_MEDIA_SENSE +* @flag IRLAP_BAD_OPSTATUS | Invalid return status for operation +* @flag IRLAP_BAD_STATE | CONTROL_CONF in invalid state +* +* @parm IRDA_MSG * | pMsg | pointer to an IRDA_MSG +* +* @comm +* comments +* +*/ +UINT +ProcessMACControlConf(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg) +{ + if (pMsg->IRDA_MSG_Op != MAC_MEDIA_SENSE) + return IRLAP_BAD_OP; + + switch (pIrlapCb->State) + { + case DSCV_MEDIA_SENSE: + switch (pMsg->IRDA_MSG_OpStatus) + { + case MAC_MEDIA_CLEAR: + pIrlapCb->SlotCnt = 0; + pIrlapCb->GenNewAddr = FALSE; + + ClearDevList(&pIrlapCb->DevList); + + RetOnErr(SendDscvXIDCmd(pIrlapCb)); + + pMsg->Prim = MAC_CONTROL_REQ; + pMsg->IRDA_MSG_Op = MAC_MEDIA_SENSE; + pMsg->IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (dscv sense)"))); + RetOnErr(IrmacDown(pIrlapCb->pIrdaLinkCb,pMsg)); + + pIrlapCb->State = DSCV_QUERY; + break; + + case MAC_MEDIA_BUSY: + IMsg.Prim = IRLAP_DISCOVERY_CONF; + IMsg.IRDA_MSG_pDevList = NULL; + IMsg.IRDA_MSG_DscvStatus = MAC_MEDIA_BUSY; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + pIrlapCb->State = NDM; + break; + + default: + return IRLAP_BAD_OPSTATUS; + } + break; + + case CONN_MEDIA_SENSE: + switch (pMsg->IRDA_MSG_OpStatus) + { + case MAC_MEDIA_CLEAR: + + // Generate a random connection address + pIrlapCb->ConnAddr = IRLAP_RAND(1, 0x7e); + + pIrlapCb->RetryCnt = 0; + + RetOnErr(SendSNRM(pIrlapCb, TRUE)); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + pIrlapCb->State = SNRM_SENT; + break; + + case MAC_MEDIA_BUSY: + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = MAC_MEDIA_BUSY; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + pIrlapCb->State = NDM; + break; + + default: + return IRLAP_BAD_OPSTATUS; + } + break; + + case DSCV_QUERY: + switch (pMsg->IRDA_MSG_OpStatus) + { + case MAC_MEDIA_CLEAR: + // Nobody responded, procede as if the slot timer expired + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Media clear, making fake slot exp"))); + + SlotTimerExp(pIrlapCb); + break; + + case MAC_MEDIA_BUSY: + // Some responding, give'm more time + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Media busy, starting slot timer"))); + + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->SlotTimer); + break; + } + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessMACDataInd | Processes MAC Data +* +* @rdesc SUCCESS, otherwise one of the following error codes +* @flag ?? | invalid return status for operation +* +* @parm IRDA_MSG * | pMsg | pointer to an IRDA_MSG +* +* @comm +* +*/ +UINT +ProcessMACDataInd(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg, BOOL *pFreeMsg) +{ + int Addr = (int) IRLAP_GET_ADDR(*(pMsg->IRDA_MSG_pRead)); + int CRBit = (int) IRLAP_GET_CRBIT(*(pMsg->IRDA_MSG_pRead)); + int Cntl = (int) *(pMsg->IRDA_MSG_pRead + 1); + int PFBit = IRLAP_GET_PFBIT(Cntl); + UINT Ns = IRLAP_GET_NS(Cntl); + UINT Nr = IRLAP_GET_NR(Cntl); + int XIDFormatID = (int) *(pMsg->IRDA_MSG_pRead+2); + IRLAP_XID_DSCV_FORMAT *pXIDFormat = (IRLAP_XID_DSCV_FORMAT *) + (pMsg->IRDA_MSG_pRead + 3); + IRLAP_SNRM_FORMAT *pSNRMFormat = (IRLAP_SNRM_FORMAT *) + (pMsg->IRDA_MSG_pRead + 2); + IRLAP_UA_FORMAT *pUAFormat = (IRLAP_UA_FORMAT *) + (pMsg->IRDA_MSG_pRead + 2); + + if (Addr != pIrlapCb->ConnAddr && Addr != IRLAP_BROADCAST_CONN_ADDR) + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Ignoring, connection address %02X"), Addr)); + return SUCCESS; + } + + pIrlapCb->StatusSent = FALSE; // don't ask + + FrmRejFormat.CntlField = Cntl; // for later maybe + + // Peer has sent a frame so clear the NoResponse condition + if (pIrlapCb->NoResponse) + { + pIrlapCb->NoResponse = FALSE; + pIrlapCb->RetryCnt = 0; + pIrlapCb->WDogExpCnt = 0; + } + + switch (IRLAP_FRAME_TYPE(Cntl)) + { + /*****************/ + case IRLAP_I_FRAME: + /*****************/ + IRLAP_LOG_ACTION((pIrlapCb, TEXT("I-frame"))); + return ProcessIFrame(pIrlapCb, pMsg, + CRBit, PFBit, Ns, Nr, pFreeMsg); + + /*****************/ + case IRLAP_S_FRAME: + /*****************/ + switch (IRLAP_GET_SCNTL(Cntl)) + { + /*-----------*/ + case IRLAP_RR: + case IRLAP_RNR: + /*-----------*/ + IRLAP_LOG_ACTION((pIrlapCb, TEXT("RR/RNR-frame"))); + return ProcessRR_RNR(pIrlapCb, + IRLAP_GET_SCNTL(Cntl), + pMsg, CRBit, PFBit, Nr); + /*------------*/ + case IRLAP_SREJ: + case IRLAP_REJ: + /*------------*/ + IRLAP_LOG_ACTION((pIrlapCb, TEXT("SJREJ/REJ-frame"))); + return ProcessREJ_SREJ(pIrlapCb, + IRLAP_GET_SCNTL(Cntl), + pMsg, CRBit, PFBit, Nr); + } + break; + + /*****************/ + case IRLAP_U_FRAME: + /*****************/ + switch (IRLAP_GET_UCNTL(Cntl)) + { + /*---------------*/ + case IRLAP_XID_CMD: + /*---------------*/ + // Should always be a command + if (CRBit != IRLAP_CMD) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received XID cmd with CRBit = rsp"))); + return IRLAP_XID_CMD_RSP; + } + // Poll bit should always be set + if (PFBit != IRLAP_PFBIT_SET) + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Received XID command without Poll set"))); + return IRLAP_XID_CMD_NOT_P; + } + + if (XIDFormatID == IRLAP_XID_DSCV_FORMAT_ID) + { + // Slot No is less than max slot or 0xff + if (pXIDFormat->SlotNo>IRLAP_SlotTable[pXIDFormat->NoOfSlots] + && pXIDFormat->SlotNo != IRLAP_END_DSCV_SLOT_NO) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Invalid slot number %d"), + pXIDFormat->SlotNo)); + return IRLAP_BAD_SLOTNO; + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("DscvXIDCmd"))); + return ProcessDscvXIDCmd(pIrlapCb, + pXIDFormat, + pMsg->IRDA_MSG_pWrite); + } + else + { + return SUCCESS; // ignore per errata + } + + /*---------------*/ + case IRLAP_XID_RSP: + /*---------------*/ + if (XIDFormatID == IRLAP_XID_DSCV_FORMAT_ID) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("DscvXIDRsp"))); + return ProcessDscvXIDRsp(pIrlapCb, + pXIDFormat,pMsg->IRDA_MSG_pWrite); + } + else + { + return SUCCESS; // ignore per errata + } + + /*------------*/ + case IRLAP_SNRM: // or IRLAP_RNRM + /*------------*/ + if (IRLAP_PFBIT_SET != PFBit) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received SNRM/RNRM without P set"))); + return IRLAP_SNRM_NOT_P; + } + if (IRLAP_CMD == CRBit) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("SNRM"))); + return ProcessSNRM(pIrlapCb, + pSNRMFormat, + pMsg->IRDA_MSG_pWrite); + } + else + { + return ProcessRNRM(pIrlapCb); + } + + /*----------*/ + case IRLAP_UA: + /*----------*/ + if (CRBit != IRLAP_RSP) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received UA as a command"))); + return IRLAP_UA_NOT_RSP; + } + if (PFBit != IRLAP_PFBIT_SET) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received UA without F set"))); + return IRLAP_UA_NOT_F; + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("UA"))); + return ProcessUA(pIrlapCb, pUAFormat, pMsg->IRDA_MSG_pWrite); + + /*------------*/ + case IRLAP_DISC: // or IRLAP_RD + /*------------*/ + if (IRLAP_PFBIT_SET != PFBit) + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Received DISC/RD command without Poll set"))); + return IRLAP_DISC_CMD_NOT_P; + } + if (IRLAP_CMD == CRBit) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("DISC"))); + return ProcessDISC(pIrlapCb); + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("RD"))); + return ProcessRD(pIrlapCb); + } + + /*----------*/ + case IRLAP_UI: + /*----------*/ + IRLAP_LOG_ACTION((pIrlapCb, TEXT("UI"))); + return ProcessUI(pIrlapCb, pMsg, CRBit, PFBit); + + /*------------*/ + case IRLAP_TEST: + /*------------*/ + IRLAP_LOG_ACTION((pIrlapCb, TEXT("TEST"))); + return ProcessTEST(pIrlapCb, pMsg, pUAFormat, CRBit, PFBit); + + /*------------*/ + case IRLAP_FRMR: + /*------------*/ + if (IRLAP_RSP != CRBit) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received FRMR cmd (must be resp)"))); + return IRLAP_FRMR_RSP_CMD; + } + if (IRLAP_PFBIT_SET != PFBit) + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Received FRMR resp without Final set"))); + return IRLAP_FRMR_RSP_NOT_F; + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("FRMR"))); + return ProcessFRMR(pIrlapCb); + + /*----------*/ + case IRLAP_DM: + /*----------*/ + if (IRLAP_RSP != CRBit) + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Received DM command (must be response)"))); + return IRLAP_DM_RSP_CMD; + } + if (IRLAP_PFBIT_SET != PFBit) + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Received DM response without Final set"))); + return IRLAP_DM_RSP_NOT_F; + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("DM"))); + return ProcessDM(pIrlapCb); + } + break; + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessDscvXIDCmd | Process received XID Discovery command +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +*/ +UINT +ProcessDscvXIDCmd(PIRLAP_CB pIrlapCb, + IRLAP_XID_DSCV_FORMAT *pXIDFormat, + BYTE *pEndDscvInfoByte) +{ + if (!MyDevAddr(pIrlapCb, pXIDFormat->DestAddr)) + { +/* IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring XID addressed to:%02X%02X%02X%02X"), + EXPAND_ADDR(pXIDFormat->DestAddr)));*/ + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring XID addressed to %X"), + pXIDFormat->DestAddr)); + return SUCCESS; + } + + if (pXIDFormat->SlotNo == IRLAP_END_DSCV_SLOT_NO) + { + pIrlapCb->GenNewAddr = FALSE; + switch (pIrlapCb->State) + { + case DSCV_QUERY: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->SlotTimer); + + IMsg.Prim = IRLAP_DISCOVERY_CONF; + IMsg.IRDA_MSG_pDevList = NULL; + IMsg.IRDA_MSG_DscvStatus = + IRLAP_REMOTE_DISCOVERY_IN_PROGRESS; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + // fall through. Send indication to LMP + + case DSCV_REPLY: + if (pIrlapCb->State == DSCV_REPLY) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->QueryTimer); + } + + // Place the device information in the control block + ExtractDeviceInfo(&pIrlapCb->RemoteDevice, pXIDFormat, + pEndDscvInfoByte); + + if (!DevInDevList(pXIDFormat->SrcAddr, &pIrlapCb->DevList)) + { + RetOnErr(AddDevToList(pIrlapCb, + pXIDFormat, + pEndDscvInfoByte)); + } + + // Notifiy LMP + IMsg.Prim = IRLAP_DISCOVERY_IND; + IMsg.IRDA_MSG_pDevList = &pIrlapCb->DevList; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + pIrlapCb->State = NDM; + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring End XID in this state"))); + } + } + else // in middle of discovery process + { + switch (pIrlapCb->State) + { + case DSCV_MEDIA_SENSE: + IMsg.Prim = IRLAP_DISCOVERY_CONF; + IMsg.IRDA_MSG_pDevList = NULL; + IMsg.IRDA_MSG_DscvStatus = + IRLAP_REMOTE_DISCOVERY_IN_PROGRESS; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + // fall through + + case NDM: + RetOnErr(InitDscvCmdProcessing(pIrlapCb, pXIDFormat)); + pIrlapCb->State = DSCV_REPLY; + break; + + case DSCV_QUERY: + IMsg.Prim = IRLAP_DISCOVERY_CONF; + IMsg.IRDA_MSG_pDevList = NULL; + IMsg.IRDA_MSG_DscvStatus = IRLAP_DISCOVERY_COLLISION; + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->SlotTimer); + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + pIrlapCb->State = NDM; + break; + + case DSCV_REPLY: + if (pXIDFormat->GenNewAddr) + { + pIrlapCb->GenNewAddr = TRUE; + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->QueryTimer); + RetOnErr(InitDscvCmdProcessing(pIrlapCb, pXIDFormat)); + } + else + { + if (pIrlapCb->RespSlot <= pXIDFormat->SlotNo && + !pIrlapCb->DscvRespSent) + { + RetOnErr(SendDscvXIDRsp(pIrlapCb)); + pIrlapCb->DscvRespSent = TRUE; + } + } + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +void +ExtractDeviceInfo(IRDA_DEVICE *pDevice, IRLAP_XID_DSCV_FORMAT *pXIDFormat, + BYTE *pEndDscvInfoByte) +{ + memcpy(pDevice->DevAddr, pXIDFormat->SrcAddr, IRDA_DEV_ADDR_LEN); + pDevice->IRLAP_Version = pXIDFormat->Version; + + // ??? what about DscvMethod + + pDevice->DscvInfoLen = pEndDscvInfoByte > &pXIDFormat->FirstDscvInfoByte ? + pEndDscvInfoByte-&pXIDFormat->FirstDscvInfoByte : + 0; + memcpy(pDevice->DscvInfo, &pXIDFormat->FirstDscvInfoByte, + pDevice->DscvInfoLen); +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +InitDscvCmdProcessing(PIRLAP_CB pIrlapCb, + IRLAP_XID_DSCV_FORMAT *pXIDFormat) +{ + pIrlapCb->RemoteMaxSlot = IRLAP_SlotTable[pXIDFormat->NoOfSlots]; + + pIrlapCb->RespSlot = IRLAP_RAND(pXIDFormat->SlotNo, + pIrlapCb->RemoteMaxSlot - 1); + + memcpy(pIrlapCb->RemoteDevice.DevAddr, pXIDFormat->SrcAddr, IRDA_DEV_ADDR_LEN); + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Responding in slot %d to device %02X%02X%02X%02X"), + pIrlapCb->RespSlot, + pIrlapCb->RemoteDevice.DevAddr[0], + pIrlapCb->RemoteDevice.DevAddr[1], + pIrlapCb->RemoteDevice.DevAddr[2], + pIrlapCb->RemoteDevice.DevAddr[3])); + + if (pIrlapCb->RespSlot == pXIDFormat->SlotNo) + { + RetOnErr(SendDscvXIDRsp(pIrlapCb)); + pIrlapCb->DscvRespSent = TRUE; + } + else + { + pIrlapCb->DscvRespSent = FALSE; + } + + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->QueryTimer); + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessDscvXIDRsp | Process received XID Discovery response +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +*/ +UINT +ProcessDscvXIDRsp(PIRLAP_CB pIrlapCb, + IRLAP_XID_DSCV_FORMAT *pXIDFormat, + BYTE *pEndDscvInfoByte) +{ + if (pIrlapCb->State == DSCV_QUERY) + { + + if (DevInDevList(pXIDFormat->SrcAddr, &pIrlapCb->DevList)) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->SlotTimer); + pIrlapCb->SlotCnt = 0; + pIrlapCb->GenNewAddr = TRUE; + ClearDevList(&pIrlapCb->DevList); + RetOnErr(SendDscvXIDCmd(pIrlapCb)); + + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE; + IMsg.IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (dscv sense)"))); + RetOnErr(IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg)); + } + else + { + RetOnErr(AddDevToList(pIrlapCb, pXIDFormat, pEndDscvInfoByte)); + } + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + + + return SUCCESS; +} +/***************************************************************************** +* +* @func BOOL | DevInDevList | Determines if given device is already in list +* +* @rdesc returns: +* @flag TRUE | if device is alreay in list +* @flag FALSE | if device is not in list +* +* @parm BYTE | DevAddr[] | Device address +* @parm IRDA_DEVICE * | pDevList | pointer to list of devices +* +*/ +BOOL +DevInDevList(BYTE DevAddr[], LIST_ENTRY *pDevList) +{ + IRDA_DEVICE *pDevice; + + pDevice = (IRDA_DEVICE *) pDevList->Flink; + + while (pDevList != (LIST_ENTRY *) pDevice) + { + if (memcmp(pDevice->DevAddr, DevAddr, IRDA_DEV_ADDR_LEN) == 0) + return (TRUE); + + pDevice = (IRDA_DEVICE *) pDevice->Linkage.Flink; + } + return (FALSE); +} +/***************************************************************************** +* +* @func void | AddDevToList | Adds elements in a device list +* +* @parm IRDA_DEVICE ** | ppDevList | address of pointer to an +* IRDA device list +* +*/ +UINT +AddDevToList(PIRLAP_CB pIrlapCb, + IRLAP_XID_DSCV_FORMAT *pXIDFormat, + BYTE *pEndDscvInfoByte) +{ + IRDA_DEVICE *pDevice; + + if (IRDA_ALLOC_MEM(pDevice, sizeof(IRDA_DEVICE), MT_IRLAP_DEVICE) == NULL) + { + return (IRLAP_MALLOC_FAILED); + } + else + { + ExtractDeviceInfo(pDevice, pXIDFormat, pEndDscvInfoByte); + + InsertTailList(&pIrlapCb->DevList, &(pDevice->Linkage)); + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("%02X%02X%02X%02X added to Device List"), + EXPAND_ADDR(pDevice->DevAddr))); + } + return SUCCESS; +} +/***************************************************************************** +* +* @func void | ClearDevList | Frees elements in a device list +* +* @parm IRDA_DEVICE ** | ppDevList | address of pointer to an +* IRDA device list +* +*/ +void +ClearDevList(LIST_ENTRY *pDevList) +{ + IRDA_DEVICE *pDevice; + + while (IsListEmpty(pDevList) == FALSE) + { + pDevice = (IRDA_DEVICE *) RemoveHeadList(pDevList); + IRDA_FREE_MEM(pDevice); + } + + //IRLAP_LOG_ACTION((pIrlapCb, TEXT("Device list cleared"))); +} +/***************************************************************************** +* +* @func UINT | ProcessSNRM | process received SNRM frame +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm IRLAP_SNRM_FORMAT * | pSNRMFormat | Pointer to SNRM frame +* Information Field +* BYTE * | pLastQosByte | Pointer to last byte in SNRM +* +* @comm +* comments +*/ +UINT +ProcessSNRM(PIRLAP_CB pIrlapCb, + IRLAP_SNRM_FORMAT *pSNRMFormat, + BYTE *pEndQosByte) +{ + BOOL Qos_InSNRM = &pSNRMFormat->FirstQosByte < pEndQosByte;// Is there Qos? + BOOL Addrs_InSNRM = (BYTE *)pSNRMFormat < pEndQosByte; + + if (Addrs_InSNRM) + { + if (!MyDevAddr(pIrlapCb, pSNRMFormat->DestAddr)) + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Ignoring SNRM addressed to:%02X%02X%02X%02X"), + EXPAND_ADDR(pSNRMFormat->DestAddr))); + return SUCCESS; + } + memcpy(pIrlapCb->RemoteDevice.DevAddr, + pSNRMFormat->SrcAddr, IRDA_DEV_ADDR_LEN); + } + + switch (pIrlapCb->State) + { + case DSCV_MEDIA_SENSE: + case DSCV_QUERY: + // In the middle of discovery... End discovery and reply to SNRM + IMsg.Prim = IRLAP_DISCOVERY_CONF; + IMsg.IRDA_MSG_pDevList = NULL; + IMsg.IRDA_MSG_DscvStatus = IRLAP_REMOTE_CONNECTION_IN_PROGRESS; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + // fall through and send connect indication + case DSCV_REPLY: + case NDM: + if (Addrs_InSNRM) + { + pIrlapCb->SNRMConnAddr = (int)IRLAP_GET_ADDR(pSNRMFormat->ConnAddr); + } + if (Qos_InSNRM) + { + ExtractQosParms(&pIrlapCb->RemoteQos, &pSNRMFormat->FirstQosByte, + pEndQosByte); + + RetOnErr(NegotiateQosParms(pIrlapCb, &pIrlapCb->RemoteQos)); + } + + memcpy(IMsg.IRDA_MSG_RemoteDevAddr, + pIrlapCb->RemoteDevice.DevAddr, IRDA_DEV_ADDR_LEN); + IMsg.IRDA_MSG_pQOS = &pIrlapCb->NegotiatedQos; + IMsg.Prim = IRLAP_CONNECT_IND; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + pIrlapCb->State = SNRM_RECEIVED; + break; + + case BACKOFF_WAIT: // CROSSED SNRM + // if Remote address greater than mine we'll respond to SNRM + if (Addrs_InSNRM) + { + if (memcmp(pSNRMFormat->SrcAddr, + pIrlapCb->LocalDevice.DevAddr, IRDA_DEV_ADDR_LEN) > 0) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->BackoffTimer); + } + } + // fall through + case CONN_MEDIA_SENSE: // CROSSED SNRM + case SNRM_SENT: + // if Remote address greater than mine we'll respond to SNRM + if (Addrs_InSNRM && + memcmp(pSNRMFormat->SrcAddr, + pIrlapCb->LocalDevice.DevAddr, IRDA_DEV_ADDR_LEN) > 0) + { + if (pIrlapCb->State != BACKOFF_WAIT) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + } + InitializeState(pIrlapCb, SECONDARY); + + if (Qos_InSNRM) + { + ExtractQosParms(&pIrlapCb->RemoteQos, + &pSNRMFormat->FirstQosByte, pEndQosByte); + RetOnErr(NegotiateQosParms(pIrlapCb,&pIrlapCb->RemoteQos)); + } + + if (Addrs_InSNRM) + { + pIrlapCb->ConnAddr = (int)IRLAP_GET_ADDR(pSNRMFormat->ConnAddr); + } + + RetOnErr(SendUA(pIrlapCb, TRUE)); + + if (Qos_InSNRM) + { + RetOnErr(ApplyQosParms(pIrlapCb)); + } + + IMsg.IRDA_MSG_pQOS = &pIrlapCb->NegotiatedQos; + IMsg.Prim = IRLAP_CONNECT_CONF; + IMsg.IRDA_MSG_ConnStatus = IRLAP_CONNECTION_COMPLETED; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + pIrlapCb->State = S_NRM; + } + break; + + case P_RECV: + case P_DISCONNECT_PEND: + case P_CLOSE: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(StationConflict(pIrlapCb)); + RetOnErr(ReturnTxMsgs(pIrlapCb)); + if (pIrlapCb->State == P_CLOSE) + { + RetOnErr(GotoNDMThenDscvOrConn(pIrlapCb)); + } + else + { + pIrlapCb->State = NDM; + } + break; + + case S_NRM: + case S_CLOSE: + case S_DISCONNECT_PEND: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(SendDM(pIrlapCb)); + RetOnErr(ApplyDefaultParms(pIrlapCb)); + IMsg.Prim = IRLAP_DISCONNECT_IND; + if (pIrlapCb->State == S_NRM) + { + IMsg.IRDA_MSG_DiscStatus = IRLAP_DECLINE_RESET; + } + else + { + IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED; + } + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + pIrlapCb->State = NDM; + break; + + case S_ERROR: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(SendFRMR(pIrlapCb, &FrmRejFormat)); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + pIrlapCb->State = S_NRM; + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("SNRM ignored in this state"))); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ProcessUA | process received UA frame +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm IRLAP_UA_FORMAT * | pUAFormat | Pointer to UA frame +* Information Field +* BYTE * | pLastQosByte | Pointer to last byte in SNRM +* +* @comm +* When &pUAFormat->FirstQosByte = pLastQosByte there is no Qos in UA +*/ +UINT +ProcessUA(PIRLAP_CB pIrlapCb, + IRLAP_UA_FORMAT *pUAFormat, + BYTE *pEndQosByte) +{ + BOOL Qos_InUA = &pUAFormat->FirstQosByte < pEndQosByte;// Is there QOS? + BOOL Addrs_InUA = (BYTE *)pUAFormat < pEndQosByte; + int Tmp; + + if (Addrs_InUA && !MyDevAddr(pIrlapCb, pUAFormat->DestAddr)) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring UA addressed to:%02X%02X%02X%02X"), + EXPAND_ADDR(pUAFormat->DestAddr))); + return SUCCESS; + } + + switch (pIrlapCb->State) + { + case BACKOFF_WAIT: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->BackoffTimer); + // fall through + case SNRM_SENT: + if (pIrlapCb->State != BACKOFF_WAIT) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + } + + InitializeState(pIrlapCb, PRIMARY); + + if (Qos_InUA) + { + ExtractQosParms(&pIrlapCb->RemoteQos, &pUAFormat->FirstQosByte, + pEndQosByte); + + RetOnErr(NegotiateQosParms(pIrlapCb,&pIrlapCb->RemoteQos)); + + RetOnErr(ApplyQosParms(pIrlapCb)); + } + + IMsg.IRDA_MSG_pQOS = &pIrlapCb->NegotiatedQos; + + IMsg.Prim = IRLAP_CONNECT_CONF; + IMsg.IRDA_MSG_ConnStatus = IRLAP_CONNECTION_COMPLETED; + + // notify LMP of connection + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + + // send RR (turn link), start FinalTimer/2 + RetOnErr(SendRR_RNR(pIrlapCb)); + + Tmp = pIrlapCb->FinalTimer.Timeout; + pIrlapCb->FinalTimer.Timeout = pIrlapCb->FinalTimer.Timeout/2; + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + pIrlapCb->FinalTimer.Timeout = Tmp; + + pIrlapCb->State = P_RECV; + break; + + case P_RECV: // Unsolicited UA, may want to do something else ??? + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->PollTimer); + pIrlapCb->State = P_XMIT; + break; + + case P_DISCONNECT_PEND: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(SendDISC(pIrlapCb)); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + pIrlapCb->RetryCnt = 0; + RetOnErr(GotoPCloseState(pIrlapCb)); + break; + + case P_CLOSE: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(ApplyDefaultParms(pIrlapCb)); + if (pIrlapCb->LocalDiscReq == TRUE) + { + pIrlapCb->LocalDiscReq = FALSE; + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + } + RetOnErr(GotoNDMThenDscvOrConn(pIrlapCb)); + break; + + case S_NRM: + case S_DISCONNECT_PEND: + case S_ERROR: + case S_CLOSE: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("UA ignored in this state"))); + } + + return SUCCESS; +} + +BYTE * +GetPv(BYTE *pQosByte, + UINT *pBitField) +{ + int Pl = (int) *pQosByte++; + + *pBitField = 0; + + if (Pl == 1) + { + *pBitField = (UINT) *pQosByte; + } + else + { + *pBitField = ((UINT) *pQosByte)<<8; + *pBitField |= (UINT) *(pQosByte+1); + } + + return pQosByte + Pl; +} +/***************************************************************************** +* +* @func void | ExtractQosParms | Extracts Qos from SNRM/UA/XID and +* places in an IRDA_QOS_PARM struct +* +* @parm IRDA_QOS_PARMS * | pIRDA_QOSParms | Pointer to QOS parm struct +* BYTE * | pQOSByte | Pointer to first byte of +* QOS in frame +* BYTE * | pEndQOSByte | Pointer to last byte of +* QOS in frame +* @comm +* THIS WILL BREAK IF PARAMETER LENGTH (PL) IS GREATER THAN 2 +*/ +void +ExtractQosParms(IRDA_QOS_PARMS *pQos, + BYTE *pQosByte, + BYTE *pEndQosByte) +{ + while (pQosByte + 2 < pEndQosByte) + { + switch (*pQosByte) + { + case QOS_PI_BAUD: + pQosByte = GetPv(pQosByte, &pQos->bfBaud); + break; + + case QOS_PI_MAX_TAT: + pQosByte = GetPv(pQosByte, &pQos->bfMaxTurnTime); + break; + + case QOS_PI_DATA_SZ: + pQosByte = GetPv(pQosByte, &pQos->bfDataSize); + break; + + case QOS_PI_WIN_SZ: + pQosByte = GetPv(pQosByte, &pQos->bfWindowSize); + break; + + case QOS_PI_BOFS: + pQosByte = GetPv(pQosByte, &pQos->bfBofs); + break; + + case QOS_PI_MIN_TAT: + pQosByte = GetPv(pQosByte, &pQos->bfMinTurnTime); + break; + + case QOS_PI_DISC_THRESH: + pQosByte = GetPv(pQosByte, &pQos->bfDisconnectTime); + break; + + default: + pQosByte += (*(pQosByte+1)); + } + } +} +/***************************************************************************** +* +* @func UINT | NegotiateQosParms | Take the received Qos build +* negotiated Qos. +* +* @rdesc SUCCESS, otherwise one of the folowing: +* @flag IRLAP_BAUD_NEG_ERR | Failed to negotiate baud +* @flag IRLAP_DISC_NEG_ERR | Failed to negotiate disconnect time +* @flag IRLAP_MAXTAT_NEG_ERR | Failed to negotiate max turn time +* @flag IRLAP_DATASIZE_NEG_ERR | Failed to negotiate data size +* @flag IRLAP_WINSIZE_NEG_ERR | Failed to negotiate window size +* @flag IRLAP_BOFS_NEG_ERR | Failed to negotiate number of BOFS +* @flag IRLAP_WINSIZE_NEG_ERR | Failed to window size +* @flag IRLAP_LINECAP_ERR | Failed to determine valid line capacity +* +* @parm IRDA_QOS_PARMS * | pRemoteQos | Pointer to QOS parm struct +*/ +UINT +NegotiateQosParms(PIRLAP_CB pIrlapCb, + IRDA_QOS_PARMS *pRemoteQos) +{ + UINT BitSet; + BOOL ParmSet = FALSE; + UINT BOFSDivisor = 1; + UINT MaxLineCap = 0; + UINT LineCapacity; + UINT DataSizeBit = 0; + UINT WinSizeBit = 0; + UINT WSBit; + int RemoteDataSize = 0; + int RemoteWinSize = 0; + + // Baud rate is Type 0 parm + pIrlapCb->Baud = IrlapGetQosParmVal(vBaudTable, + (BYTE) (pIrlapCb->LocalQos.bfBaud & pRemoteQos->bfBaud), + &BitSet); + BOFSDivisor = IrlapGetQosParmVal(vBOFSDivTable, + (BYTE) (pIrlapCb->LocalQos.bfBaud & pRemoteQos->bfBaud), + &BitSet); + pIrlapCb->NegotiatedQos.bfBaud = BitSet; + + if (-1 == pIrlapCb->Baud) + { + return (IRLAP_BAUD_NEG_ERR); + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Negotiated Baud:%d"), pIrlapCb->Baud)); + + // Disconnect/Threshold time is Type 0 parm + pIrlapCb->DisconnectTime = IrlapGetQosParmVal(vDiscTable, + (BYTE)(pIrlapCb->LocalQos.bfDisconnectTime & + pRemoteQos->bfDisconnectTime), &BitSet); + pIrlapCb->ThresholdTime = IrlapGetQosParmVal(vThreshTable, + (BYTE)(pIrlapCb->LocalQos.bfDisconnectTime & + pRemoteQos->bfDisconnectTime), &BitSet); + pIrlapCb->NegotiatedQos.bfDisconnectTime = BitSet; + + if (-1 == pIrlapCb->DisconnectTime) + { + return (IRLAP_DISC_NEG_ERR); + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Negotiated Disconnect/Threshold time:%d/%d"), + pIrlapCb->DisconnectTime, pIrlapCb->ThresholdTime)); + + pIrlapCb->RemoteMaxTAT = IrlapGetQosParmVal(vMaxTATTable, + pRemoteQos->bfMaxTurnTime, + &BitSet); + pIrlapCb->NegotiatedQos.bfMaxTurnTime = BitSet; + if (-1 == pIrlapCb->RemoteMaxTAT) + { + return (IRLAP_MAXTAT_NEG_ERR); + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote max turnaround time:%d"), + pIrlapCb->RemoteMaxTAT)); + + pIrlapCb->RemoteMinTAT = IrlapGetQosParmVal(vMinTATTable, + pRemoteQos->bfMinTurnTime, + &BitSet); + pIrlapCb->NegotiatedQos.bfMinTurnTime = BitSet; + if (-1 == pIrlapCb->RemoteMinTAT) + { + return (IRLAP_MINTAT_NEG_ERR); + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote min turnaround time:%d"), + pIrlapCb->RemoteMinTAT)); + + // DataSize ISNOT A TYPE 0 PARAMETER. BUT WIN95's IRCOMM implementation + // ASSUMES THAT IT IS. SO FOR NOW, NEGOTIATE IT. grrrr.. + /* WIN95 out + pIrlapCb->RemoteDataSize = IrlapGetQosParmVal(vDataSizeTable, + (BYTE) (pIrlapCb->LocalQos.bfDataSize & + pRemoteQos->bfDataSize), &BitSet); + */ + pIrlapCb->RemoteDataSize = IrlapGetQosParmVal(vDataSizeTable, + pRemoteQos->bfDataSize, &BitSet); + DataSizeBit = BitSet; + pIrlapCb->NegotiatedQos.bfDataSize = BitSet; + if (-1 == pIrlapCb->RemoteDataSize) + { + return (IRLAP_DATASIZE_NEG_ERR); + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote data size:%d"), pIrlapCb->RemoteDataSize)); + + pIrlapCb->RemoteWinSize = IrlapGetQosParmVal(vWinSizeTable, + pRemoteQos->bfWindowSize, &BitSet); + WinSizeBit = BitSet; + pIrlapCb->NegotiatedQos.bfWindowSize = BitSet; + if (-1 == pIrlapCb->RemoteWinSize) + { + return (IRLAP_WINSIZE_NEG_ERR); + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote window size:%d"), pIrlapCb->RemoteWinSize)); + + pIrlapCb->RemoteNumBOFS=(IrlapGetQosParmVal(vBOFSTable, + pRemoteQos->bfBofs, &BitSet) + / BOFSDivisor)+1; + pIrlapCb->NegotiatedQos.bfBofs = BitSet; + if (-1 == pIrlapCb->RemoteNumBOFS) + { + return (IRLAP_BOFS_NEG_ERR); + } + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote number of BOFS:%d"), + pIrlapCb->RemoteNumBOFS)); + + // The maximum line capacity is in bytes and comes from a table in spec. + // (can't calc because table isn't linear). It is determined by the + // maximum line capacity and baud rate. + // + // Later note: Errata corrected table so values could be calculated. + // Could get rid of tables + switch (pIrlapCb->Baud) + { + case 9600: + MaxLineCap = IrlapGetQosParmVal(MAXCAP_9600, + pRemoteQos->bfMaxTurnTime, &BitSet); + break; + + case 19200: + MaxLineCap = IrlapGetQosParmVal(MAXCAP_19200, + pRemoteQos->bfMaxTurnTime, &BitSet); + break; + + case 38400: + MaxLineCap = IrlapGetQosParmVal(MAXCAP_38400, + pRemoteQos->bfMaxTurnTime, &BitSet); + break; + + case 57600: + MaxLineCap = IrlapGetQosParmVal(MAXCAP_57600, + pRemoteQos->bfMaxTurnTime, &BitSet); + break; + + case 115200: + MaxLineCap = IrlapGetQosParmVal(MAXCAP_115200, + pRemoteQos->bfMaxTurnTime, &BitSet); + break; + } + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Maximum line capacity:%d"), MaxLineCap)); + LineCapacity = LINE_CAPACITY(pIrlapCb); + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Requested line capacity:%d"), LineCapacity)); + + if (LineCapacity > MaxLineCap) + { + ParmSet = FALSE; + // Adjust data and window size to fit within the line capacity. + // Get largest possible datasize + for (; DataSizeBit != 0 && !ParmSet; DataSizeBit >>= 1) + { + pIrlapCb->RemoteDataSize = IrlapGetQosParmVal(vDataSizeTable, + DataSizeBit, NULL); + // Start with smallest window + for (WSBit=1; WSBit <= WinSizeBit; WSBit <<=1) + { + pIrlapCb->RemoteWinSize = IrlapGetQosParmVal(vWinSizeTable, + WSBit, NULL); + LineCapacity = LINE_CAPACITY(pIrlapCb); + + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("adjusted data size=%d, window size= %d, line cap=%d"), + pIrlapCb->RemoteDataSize, pIrlapCb->RemoteWinSize, + LineCapacity)); + + if (LineCapacity > MaxLineCap) + { + break; // Get a smaller data size (only if ParmSet is false) + } + ParmSet = TRUE; + // Save the last good one,then loop and try a larger window + RemoteDataSize = pIrlapCb->RemoteDataSize; + RemoteWinSize = pIrlapCb->RemoteWinSize; + pIrlapCb->NegotiatedQos.bfWindowSize = WSBit; + pIrlapCb->NegotiatedQos.bfDataSize = DataSizeBit; + } + } + if (!ParmSet) + { + return (IRLAP_LINECAP_ERR); + } + + pIrlapCb->RemoteDataSize = RemoteDataSize; + pIrlapCb->RemoteWinSize = RemoteWinSize; + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("final data size=%d, window size= %d, line cap=%d"), + pIrlapCb->RemoteDataSize, pIrlapCb->RemoteWinSize, + LINE_CAPACITY(pIrlapCb))); + } + + return (SUCCESS); +} +/***************************************************************************** +* +* @func UINT | ApplyQosParms | Apply negotiated Qos in control block +* +* @rdesc return status from IrmacDown() +*/ +UINT +ApplyQosParms(PIRLAP_CB pIrlapCb) +{ + // convert disconnect/threshold time to ms and divide by turn around time + // to get number of retries + pIrlapCb->N1 = pIrlapCb->ThresholdTime * 1000 / pIrlapCb->RemoteMaxTAT; + pIrlapCb->N2 = pIrlapCb->DisconnectTime * 1000 / pIrlapCb->RemoteMaxTAT; + + // hmmmm...??? + pIrlapCb->PollTimer.Timeout = pIrlapCb->RemoteMaxTAT; + pIrlapCb->FinalTimer.Timeout = pIrlapCb->LocalMaxTAT; + + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_RECONFIG_LINK; + IMsg.IRDA_MSG_Baud = pIrlapCb->Baud; + IMsg.IRDA_MSG_NumBOFs = pIrlapCb->RemoteNumBOFS; // Number of BOFS + // to add to tx + IMsg.IRDA_MSG_DataSize = pIrlapCb->RemoteDataSize; // Max rx size packet + // causes major heap + // problems later + IMsg.IRDA_MSG_MinTat = pIrlapCb->RemoteMinTAT; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Reconfig link for Baud:%d, Local data size:%d, Remote BOFS:%d"), pIrlapCb->Baud, pIrlapCb->LocalDataSize, pIrlapCb->RemoteNumBOFS)); + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Retry counts N1=%d, N2=%d"), pIrlapCb->N1, pIrlapCb->N2)); + return (IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg)); +} +/***************************************************************************** +* +* @func UINT | IrlapGetQosParmVal | +* retrieves the parameters value from table +* +* @rdesc value contained in parmeter value table, 0 if not found +* (0 is a valid parameter in some tables though) +* +* @parm UINT [] | PVTable | table containing parm values +* USHORT | BitField | contains bit indicating which parm to select +* +* @comm +*/ +UINT +IrlapGetQosParmVal(UINT PVTable[], UINT BitField, UINT *pBitSet) +{ + int i; + UINT Mask; + + for (i = PV_TABLE_MAX_BIT, Mask = (1< 0; i--, Mask = Mask >> 1) + { + if (Mask & BitField) + { + if (pBitSet != NULL) + { + *pBitSet = Mask; + } + return (PVTable[i]); + } + } + return (UINT) -1; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessTEST(PIRLAP_CB pIrlapCb, + PIRDA_MSG pMsg, + IRLAP_UA_FORMAT *pTestFormat, + int CRBit, + int PFBit) +{ + BYTE TmpAddr[IRDA_DEV_ADDR_LEN]; + + if (!MyDevAddr(pIrlapCb, pTestFormat->DestAddr)) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring XID addressed to:%02X%02X%02X%02X"), + EXPAND_ADDR(pTestFormat->DestAddr))); + return SUCCESS; + } + + if (IRLAP_CMD == CRBit && IRLAP_PFBIT_SET == PFBit) + { + // bounce it back + memcpy(TmpAddr,pTestFormat->SrcAddr, IRDA_DEV_ADDR_LEN); + memcpy(pTestFormat->SrcAddr, pTestFormat->DestAddr, IRDA_DEV_ADDR_LEN); + memcpy(pTestFormat->DestAddr, TmpAddr, IRDA_DEV_ADDR_LEN); + *(pMsg->IRDA_MSG_pRead) ^= 1; // swap cr bit + return SendFrame(pIrlapCb, pMsg); + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring"))); + } + + // Not implementing TEST responses for now + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessUI(PIRLAP_CB pIrlapCb, + PIRDA_MSG pMsg, + int CRBit, + int PFBit) +{ + BOOL LinkTurned = TRUE; + + pMsg->IRDA_MSG_pRead += 2; // chop the IRLAP header + + switch (pIrlapCb->State) + { + case NDM: + case DSCV_MEDIA_SENSE: + case DSCV_QUERY: + case DSCV_REPLY: + case CONN_MEDIA_SENSE: + case SNRM_SENT: + case BACKOFF_WAIT: + case SNRM_RECEIVED: + pMsg->Prim = IRLAP_UDATA_IND; + return (IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg)); + + case P_XMIT: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + return SUCCESS; + } + + if (PRIMARY == pIrlapCb->StationType) + { + // stop timers if PF bit set or invalid CRBit (matches mine) + if (IRLAP_PFBIT_SET == PFBit || pIrlapCb->CRBit == CRBit) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + } + + if (pIrlapCb->CRBit == CRBit) + { + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + // Send the Unnumber information to LMP + pMsg->Prim = IRLAP_UDATA_IND; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg)); + + if (IRLAP_PFBIT_SET == PFBit) + { + switch (pIrlapCb->State) + { + case P_RECV: + RetOnErr(XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned)); + break; + + case P_DISCONNECT_PEND: + RetOnErr(SendDISC(pIrlapCb)); + pIrlapCb->RetryCnt = 0; + RetOnErr(GotoPCloseState(pIrlapCb)); + break; + + case P_CLOSE: + RetOnErr(ResendDISC(pIrlapCb)); + break; + + case S_NRM: + RetOnErr(XmitTxMsgList(pIrlapCb, TRUE, NULL)); + break; + + case S_DISCONNECT_PEND: + RetOnErr(SendRD(pIrlapCb)); + pIrlapCb->State = S_CLOSE; + break; + + case S_ERROR: + RetOnErr(SendFRMR(pIrlapCb, &FrmRejFormat)); + pIrlapCb->State = S_NRM; + break; + + case S_CLOSE: + RetOnErr(SendRD(pIrlapCb)); + } + } + + if (PRIMARY == pIrlapCb->StationType) + { + if (IRLAP_PFBIT_SET == PFBit && pIrlapCb->State != NDM) + { + if (LinkTurned) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + else + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->PollTimer); + pIrlapCb->State = P_XMIT; + } + } + } + else + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessDM(PIRLAP_CB pIrlapCb) +{ + BOOL LinkTurned; + + switch (pIrlapCb->State) + { + case NDM: + case DSCV_MEDIA_SENSE: + case DSCV_QUERY: + case DSCV_REPLY: + case CONN_MEDIA_SENSE: + case BACKOFF_WAIT: + case SNRM_RECEIVED: + case P_XMIT: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + return TRUE; + } + + if (PRIMARY != pIrlapCb->StationType) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + + switch (pIrlapCb->State) + { + case P_RECV: // I'm not sure why I am doing this ??? + RetOnErr(XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned)); + if (LinkTurned) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + else + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->PollTimer); + pIrlapCb->State = P_XMIT; + } + break; + + case P_DISCONNECT_PEND: + pIrlapCb->RetryCnt = 0; + RetOnErr(SendDISC(pIrlapCb)); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(GotoPCloseState(pIrlapCb)); + break; + + case SNRM_SENT: + case P_CLOSE: + RetOnErr(ApplyDefaultParms(pIrlapCb)); + IMsg.Prim = IRLAP_DISCONNECT_IND; + if (pIrlapCb->State == P_CLOSE) + { + IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED; + } + else + { + IMsg.IRDA_MSG_DiscStatus = IRLAP_REMOTE_INITIATED; + } + if (pIrlapCb->LocalDiscReq || pIrlapCb->State == SNRM_SENT) + { + pIrlapCb->LocalDiscReq = FALSE; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + } + + if (pIrlapCb->State == P_CLOSE) + { + return GotoNDMThenDscvOrConn(pIrlapCb); + } + + pIrlapCb->State = NDM; + break; + } + + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessDISC(PIRLAP_CB pIrlapCb) +{ + if (IgnoreState(pIrlapCb)) + { + return SUCCESS; + } + + if (SECONDARY != pIrlapCb->StationType) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + + // Acknowledge primary's disconnect request + RetOnErr(SendUA(pIrlapCb, FALSE /* No Qos */)); + RetOnErr(ApplyDefaultParms(pIrlapCb)); + + RetOnErr(ReturnTxMsgs(pIrlapCb)); + + // notify LMP of disconnect + IMsg.Prim = IRLAP_DISCONNECT_IND; + if (pIrlapCb->LocalDiscReq) + { + IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED; + pIrlapCb->LocalDiscReq = FALSE; + } + else + { + IMsg.IRDA_MSG_DiscStatus = IRLAP_REMOTE_INITIATED; + } + + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + + pIrlapCb->State = NDM; + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessRD(PIRLAP_CB pIrlapCb) +{ + if (IgnoreState(pIrlapCb)) + { + return SUCCESS; + } + + if (PRIMARY != pIrlapCb->StationType) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + + if (pIrlapCb->State == P_CLOSE) + { + RetOnErr(ResendDISC(pIrlapCb)); + } + else + { + RetOnErr(ReturnTxMsgs(pIrlapCb)); + pIrlapCb->RetryCnt = 0; + RetOnErr(SendDISC(pIrlapCb)); + RetOnErr(GotoPCloseState(pIrlapCb)); + } + if (pIrlapCb->State != NDM) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessFRMR(PIRLAP_CB pIrlapCb) +{ + if (IgnoreState(pIrlapCb)) + { + return SUCCESS; + } + + if (PRIMARY != pIrlapCb->StationType) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + + switch (pIrlapCb->State) + { + case P_RECV: + RetOnErr(ReturnTxMsgs(pIrlapCb)); + // fall through + + case P_DISCONNECT_PEND: + pIrlapCb->RetryCnt = 0; + RetOnErr(SendDISC(pIrlapCb)); + RetOnErr(GotoPCloseState(pIrlapCb)); + break; + + case P_CLOSE: + RetOnErr(ResendDISC(pIrlapCb)); + break; + } + + if (pIrlapCb->State != NDM) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessRNRM(PIRLAP_CB pIrlapCb) +{ + if (IgnoreState(pIrlapCb)) + { + return SUCCESS; + } + + if (PRIMARY != pIrlapCb->StationType) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + + switch (pIrlapCb->State) + { + case P_RECV: + case P_DISCONNECT_PEND: + pIrlapCb->RetryCnt = 0; + RetOnErr(SendDISC(pIrlapCb)); + RetOnErr(GotoPCloseState(pIrlapCb)); + break; + + case P_CLOSE: + RetOnErr(ResendDISC(pIrlapCb)); + break; + } + + if (pIrlapCb->State != NDM) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessREJ_SREJ(PIRLAP_CB pIrlapCb, + int FrameType, + PIRDA_MSG pMsg, + int CRBit, + int PFBit, + UINT Nr) +{ + if (IgnoreState(pIrlapCb)) + { + return SUCCESS; + } + + if (PRIMARY == pIrlapCb->StationType) + { + // stop timers if PF bit set or invalid CRBit (matches mine) + if (IRLAP_PFBIT_SET == PFBit || pIrlapCb->CRBit == CRBit) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + } + + if (pIrlapCb->CRBit == CRBit) + { + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + switch (pIrlapCb->State) + { + case P_RECV: + case S_NRM: + if (IRLAP_PFBIT_SET == PFBit) + { + if (InvalidNr(pIrlapCb,Nr) || Nr == pIrlapCb->TxWin.End) + { + RetOnErr(ProcessInvalidNr(pIrlapCb, PFBit)); + } + else + { + RetOnErr(FreeAckedTxMsgs(pIrlapCb, Nr)); + if (FrameType == IRLAP_REJ) + { + RetOnErr(ResendRejects(pIrlapCb, Nr)); // link turned here + } + else // selective reject + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("RETRANSMISSION:"))); + RetOnErr(SendIFrame(pIrlapCb, + pIrlapCb->TxWin.pMsg[Nr], + Nr, IRLAP_PFBIT_SET)); + } + } + } + break; + + case P_DISCONNECT_PEND: + if (IRLAP_PFBIT_SET == PFBit) + { + pIrlapCb->RetryCnt = 0; + RetOnErr(SendDISC(pIrlapCb)); + RetOnErr(GotoPCloseState(pIrlapCb)); + } + break; + + case P_CLOSE: + if (IRLAP_PFBIT_SET == PFBit) + { + RetOnErr(ResendDISC(pIrlapCb)); + } + break; + + case S_DISCONNECT_PEND: + if (IRLAP_PFBIT_SET == PFBit) + { + RetOnErr(SendRD(pIrlapCb)); + pIrlapCb->State = S_CLOSE; + } + break; + + case S_ERROR: + if (IRLAP_PFBIT_SET == PFBit) + { + RetOnErr(SendFRMR(pIrlapCb, &FrmRejFormat)); + pIrlapCb->State = S_NRM; + } + break; + + case S_CLOSE: + if (IRLAP_PFBIT_SET == PFBit) + { + RetOnErr(SendRD(pIrlapCb)); + } + break; + + } + if (PRIMARY == pIrlapCb->StationType) + { + if (IRLAP_PFBIT_SET == PFBit && pIrlapCb->State != NDM) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + else + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessRR_RNR(PIRLAP_CB pIrlapCb, + int FrameType, + PIRDA_MSG pMsg, + int CRBit, + int PFBit, + UINT Nr) +{ + BOOL LinkTurned = TRUE; + + if (IgnoreState(pIrlapCb)) + { + return SUCCESS; + } + + if (PRIMARY == pIrlapCb->StationType) + { + // stop timers if PF bit set or invalid CRBit (matches mine) + if (IRLAP_PFBIT_SET == PFBit || pIrlapCb->CRBit == CRBit) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + else // SECONDARY, restart WDog + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + if (pIrlapCb->CRBit != CRBit) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + } + + if (pIrlapCb->CRBit == CRBit) + { + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + if (FrameType == IRLAP_RR) + { + pIrlapCb->RemoteBusy = FALSE; + } + else // RNR + { + pIrlapCb->RemoteBusy = TRUE; + } + + switch (pIrlapCb->State) + { + case P_RECV: + case S_NRM: + if (PFBit == IRLAP_PFBIT_SET) + { + if (InvalidNr(pIrlapCb, Nr)) + { + RetOnErr(ProcessInvalidNr(pIrlapCb, PFBit)); + } + else + { + RetOnErr(FreeAckedTxMsgs(pIrlapCb,Nr)); + + if (Nr != pIrlapCb->Vs) // Implicit reject + { + if (PRIMARY == pIrlapCb->StationType && + IRLAP_RNR == FrameType) + { + LinkTurned = FALSE; + } + else + { + RetOnErr(ResendRejects(pIrlapCb, + Nr)); // always turns link + } + } + else + { + if (pIrlapCb->Vr != pIrlapCb->RxWin.End) + { + RetOnErr(MissingRxFrames(pIrlapCb)); // Send SREJ or REJ + } + else + { + if (PRIMARY == pIrlapCb->StationType) + { + LinkTurned = FALSE; + if (IRLAP_RR == FrameType) + { + RetOnErr(XmitTxMsgList(pIrlapCb, + FALSE, &LinkTurned)); + } + } + else + { + // Always turn link if secondary + // with data or an RR if remote is busy + if (IRLAP_RR == FrameType) + { + RetOnErr(XmitTxMsgList(pIrlapCb, TRUE, NULL)); + } + else + { + RetOnErr(SendRR_RNR(pIrlapCb)); + } + } + } + } + } + // If the link was turned, restart Final timer, + // else start the Poll timer and enter the transmit state + if (PRIMARY == pIrlapCb->StationType) + { + if (LinkTurned) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + else + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->PollTimer); + pIrlapCb->State = P_XMIT; + } + } + } + break; + + case P_DISCONNECT_PEND: + RetOnErr(SendDISC(pIrlapCb)); + pIrlapCb->RetryCnt = 0; + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(GotoPCloseState(pIrlapCb)); + break; + + case P_CLOSE: + RetOnErr(ResendDISC(pIrlapCb)); + if (pIrlapCb->State != NDM) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + break; + + case S_DISCONNECT_PEND: + case S_CLOSE: + if (IRLAP_PFBIT_SET == PFBit) + { + RetOnErr(SendRD(pIrlapCb)); + if (pIrlapCb->State != S_CLOSE) + pIrlapCb->State = S_CLOSE; + } + break; + + case S_ERROR: + if (IRLAP_PFBIT_SET == PFBit) + { + RetOnErr(SendFRMR(pIrlapCb, &FrmRejFormat)); + pIrlapCb->State = S_NRM; + } + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessInvalidNr(PIRLAP_CB pIrlapCb, + int PFBit) +{ + DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: ERROR, Invalid Nr\r\n"))); + + RetOnErr(ReturnTxMsgs(pIrlapCb)); + + if (PRIMARY == pIrlapCb->StationType) + { + if (PFBit == IRLAP_PFBIT_SET) + { + RetOnErr(SendDISC(pIrlapCb)); + pIrlapCb->RetryCnt = 0; + // F-timer will be started by caller + RetOnErr(GotoPCloseState(pIrlapCb)); + } + else + { + pIrlapCb->State = P_DISCONNECT_PEND; + } + } + else // SECONDARY + { + if (PFBit == IRLAP_PFBIT_SET) + { + FrmRejFormat.Vs = pIrlapCb->Vs; + FrmRejFormat.Vr = pIrlapCb->Vr; + FrmRejFormat.W = 0; + FrmRejFormat.X = 0; + FrmRejFormat.Y = 0; + FrmRejFormat.Z = 1; // bad NR + RetOnErr(SendFRMR(pIrlapCb, &FrmRejFormat)); + } + } + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessIFrame(PIRLAP_CB pIrlapCb, + PIRDA_MSG pMsg, + int CRBit, + int PFBit, + UINT Ns, + UINT Nr, + BOOL *pFreeMsg) +{ +#ifdef DEBUG + BYTE *p1, *p2; +#endif + + pMsg->IRDA_MSG_pRead += 2; // chop the IRLAP header + + switch (pIrlapCb->State) + { + case S_NRM: + case P_RECV: + // Stop Timers: if PFSet stop Final (I frame from secondary) + // Always stop WDog (I from primary) + if (PRIMARY == pIrlapCb->StationType) + { + if (PFBit == IRLAP_PFBIT_SET) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + } + + if (pIrlapCb->CRBit == CRBit) + { + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + return SUCCESS; + } + + if (InvalidNsOrNr(pIrlapCb, Ns, Nr)) + { +#ifdef DEBUG + p1 = pMsg->IRDA_MSG_pRead - 2; // Get header back + p2 = pMsg->IRDA_MSG_pWrite + 2; // and FCS + + while (p1 < p2) + DEBUGMSG(DBG_ERROR, (TEXT("%02X "), *p1++)); + DEBUGMSG(DBG_ERROR, (TEXT("\n"))); +#endif + +#ifdef TEMPERAMENTAL_SERIAL_DRIVER + if (pIrlapCb->RxWin.FCS[Ns] == pMsg->IRDA_MSG_FCS) + TossedDups++; + else + RetOnErr(ProcessInvalidNsOrNr(pIrlapCb, PFBit)); +#else + RetOnErr(ProcessInvalidNsOrNr(pIrlapCb, PFBit)); +#endif + } + else + { + if (PFBit == IRLAP_PFBIT_SET) + { + RetOnErr(InsertRxWinAndForward(pIrlapCb, + pMsg, Ns, pFreeMsg)); + + if (Nr != pIrlapCb->Vs) + { + RetOnErr(ResendRejects(pIrlapCb, Nr)); // always turns link + } + else // Nr == Vs, Good Nr + { + RetOnErr(FreeAckedTxMsgs(pIrlapCb, Nr)); + // Link will always be turned here + if (pIrlapCb->Vr != pIrlapCb->RxWin.End) + { + RetOnErr(MissingRxFrames(pIrlapCb)); + } + else + { + RetOnErr(XmitTxMsgList(pIrlapCb, TRUE, NULL)); + } + } + } + else // PF Bit not set + { + RetOnErr(InsertRxWinAndForward(pIrlapCb, + pMsg, Ns, pFreeMsg)); + RetOnErr(FreeAckedTxMsgs(pIrlapCb, Nr)); + } + } + // Start Timers: If PFBit set, link was turned so start final + // WDog is always stopped, so restart + if (PRIMARY == pIrlapCb->StationType) + { + if (PFBit == IRLAP_PFBIT_SET) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + else // command from primary + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + break; + + default: + RetOnErr(IFrameOtherStates(pIrlapCb, CRBit, PFBit)); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* +* @ex +* example +*/ +BOOL +InvalidNsOrNr(PIRLAP_CB pIrlapCb, + UINT Ns, + UINT Nr) +{ + if (InvalidNr(pIrlapCb, Nr)) + { + return TRUE; + } + + // Valididate ns + if (!InWindow(pIrlapCb->Vr, + (pIrlapCb->RxWin.Start + pIrlapCb->LocalWinSize-1) % IRLAP_MOD, Ns) + || !InWindow(pIrlapCb->RxWin.Start, + (pIrlapCb->RxWin.Start + pIrlapCb->LocalWinSize-1) % IRLAP_MOD, Ns)) + { + DEBUGMSG(DBG_ERROR, + (TEXT("IRLAP: ERROR, Invalid Ns=%d! Vr=%d, RxStrt=%d Win=%d\r\n"), + Ns, pIrlapCb->Vr, pIrlapCb->RxWin.Start, pIrlapCb->LocalWinSize)); + IRLAP_LOG_ACTION((pIrlapCb, TEXT("** INVALID Ns **"))); + return TRUE; + } + return FALSE; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* +* @ex +* example +*/ +BOOL +InvalidNr(PIRLAP_CB pIrlapCb, + UINT Nr) +{ + if (!InWindow(pIrlapCb->TxWin.Start, pIrlapCb->Vs, Nr)) + { + DEBUGMSG(DBG_ERROR, + (TEXT("IRLAP: ERROR, Invalid Nr=%d! Vs=%d, TxStrt=%d\r\n"), + Nr, pIrlapCb->Vs, pIrlapCb->TxWin.Start)); + return TRUE; // Invalid Nr + } + return FALSE; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +BOOL +InWindow(UINT Start, UINT End, UINT i) +{ + if (Start <= End) + { + if (i >= Start && i <= End) + return TRUE; + } + else + { + if (i >= Start || i <= End) + return TRUE; + } + return FALSE; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ProcessInvalidNsOrNr(PIRLAP_CB pIrlapCb, + int PFBit) +{ + RetOnErr(ReturnTxMsgs(pIrlapCb)); + + if (PRIMARY == pIrlapCb->StationType) + { + if (PFBit == IRLAP_PFBIT_SET) + { + RetOnErr(SendDISC(pIrlapCb)); + pIrlapCb->RetryCnt = 0; + // F-timer will be started by caller + RetOnErr(GotoPCloseState(pIrlapCb)); + } + else + { + pIrlapCb->State = P_DISCONNECT_PEND; + } + } + else // SECONDARY + { + FrmRejFormat.Vs = pIrlapCb->Vs; + FrmRejFormat.Vr = pIrlapCb->Vr; + FrmRejFormat.W = 0; + FrmRejFormat.X = 0; + FrmRejFormat.Y = 0; + FrmRejFormat.Z = 1; // bad NR + if (PFBit == IRLAP_PFBIT_SET) + { + RetOnErr(SendFRMR(pIrlapCb, &FrmRejFormat)); + } + else + { + pIrlapCb->State = S_ERROR; + } + } + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +InsertRxWinAndForward(PIRLAP_CB pIrlapCb, + PIRDA_MSG pMsg, + UINT Ns, + BOOL *pFreeMsg) +{ + UINT rc = SUCCESS; + + // insert message into receive window + pIrlapCb->RxWin.pMsg[Ns] = pMsg; +#ifdef TEMPERAMENTAL_SERIAL_DRIVER + pIrlapCb->RxWin.FCS[Ns] = pMsg->IRDA_MSG_FCS; +#endif + + // Advance RxWin.End to Ns+1 if Ns is at or beyond RxWin.End + if (!InWindow(pIrlapCb->RxWin.Start, pIrlapCb->RxWin.End, Ns) || + Ns == pIrlapCb->RxWin.End) + { + pIrlapCb->RxWin.End = (Ns + 1) % IRLAP_MOD; + } + + // Forward in sequence frames starting from Vr + while (pIrlapCb->RxWin.pMsg[pIrlapCb->Vr] != NULL && !pIrlapCb->LocalBusy) + { + pIrlapCb->RxWin.pMsg[pIrlapCb->Vr]->Prim = IRLAP_DATA_IND; + + rc =IrlmpUp(pIrlapCb->pIrdaLinkCb, pIrlapCb->RxWin.pMsg[pIrlapCb->Vr]); + + if (rc == SUCCESS || rc == IRLMP_LOCAL_BUSY) + { + // Delivered successfully. Done with this message. Remove it from + // the RxWin and return message to rx free list. Update Vr + +/* !!! here it is again + RetOnErr(EnqueMsgList(&pIrlapCb->RxMsgFreeList, + pIrlapCb->RxWin.pMsg[pIrlapCb->Vr], + pIrlapCb->MaxRxMsgFreeListLen)); +*/ + pIrlapCb->RxWin.pMsg[pIrlapCb->Vr] = NULL; + pIrlapCb->Vr = (pIrlapCb->Vr + 1) % IRLAP_MOD; + + // LMP doesn't want anymore messages + if (rc == IRLMP_LOCAL_BUSY) + { + // The receive window will be cleaned out when RNR is sent + pIrlapCb->LocalBusy = TRUE; + } + } + else + { + return rc; + } + } + *pFreeMsg = FALSE; // we either already freed it or placed it in the window + // i.e. the caller should not free the message + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ResendRejects(PIRLAP_CB pIrlapCb, UINT Nr) +{ + if (!pIrlapCb->RemoteBusy) + { + // Set Vs back + + for (pIrlapCb->Vs = Nr;pIrlapCb->Vs != (pIrlapCb->TxWin.End-1)%IRLAP_MOD; + pIrlapCb->Vs = (pIrlapCb->Vs + 1) % IRLAP_MOD) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("RETRANSMISSION:"))); + RetOnErr(SendIFrame(pIrlapCb, + pIrlapCb->TxWin.pMsg[pIrlapCb->Vs], + pIrlapCb->Vs, + IRLAP_PFBIT_CLEAR)); + } + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("RETRANSMISSION:"))); + // Send last one with PFBit set + RetOnErr(SendIFrame(pIrlapCb, pIrlapCb->TxWin.pMsg[pIrlapCb->Vs], + pIrlapCb->Vs, IRLAP_PFBIT_SET)); + + pIrlapCb->Vs = (pIrlapCb->Vs + 1) % IRLAP_MOD; // Vs == TxWin.End + } + else + { + RetOnErr(SendRR_RNR(pIrlapCb)); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +FreeAckedTxMsgs(PIRLAP_CB pIrlapCb, + UINT Nr) +{ + UINT i = pIrlapCb->TxWin.Start; + + while (i != Nr) + { + if (pIrlapCb->TxWin.pMsg[i] != NULL) + { + pIrlapCb->TxWin.pMsg[i]->Prim = IRLAP_DATA_CONF; + pIrlapCb->TxWin.pMsg[i]->IRDA_MSG_DataStatus = + IRLAP_DATA_REQUEST_COMPLETED; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, pIrlapCb->TxWin.pMsg[i])); + + pIrlapCb->TxWin.pMsg[i] = NULL; + } + i = (i + 1) % IRLAP_MOD; + } + pIrlapCb->TxWin.Start = i; + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +MissingRxFrames(PIRLAP_CB pIrlapCb) +{ + int MissingFrameCnt = 0; + int MissingFrame = -1; + UINT i; + + i = pIrlapCb->Vr; + + // Count missing frame, determine first missing frame + + for (i = pIrlapCb->Vr; (i + 1) % IRLAP_MOD != pIrlapCb->RxWin.End; + i = (i+1) % IRLAP_MOD) + { + if (pIrlapCb->RxWin.pMsg[i] == NULL) + { + MissingFrameCnt++; + if (MissingFrame == -1) + { + MissingFrame = i; + } + } + } + + // if there are missing frames send SREJ (1) or RR (more than 1) + // and turn link around + if (MissingFrameCnt == 1 && !pIrlapCb->LocalBusy) + { + // we don't want to send the SREJ when local is busy because + // peer *MAY* interpret it as a clearing of the local busy condition + RetOnErr(SendSREJ(pIrlapCb, MissingFrame)); + } + else + { + // The RR/RNR will serve as an implicit REJ + RetOnErr(SendRR_RNR(pIrlapCb)); + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +IFrameOtherStates(PIRLAP_CB pIrlapCb, + int CRBit, + int PFBit) +{ + switch (pIrlapCb->State) + { + case NDM: + case DSCV_MEDIA_SENSE: + case DSCV_QUERY: + case DSCV_REPLY: + case CONN_MEDIA_SENSE: + case SNRM_SENT: + case BACKOFF_WAIT: + case SNRM_RECEIVED: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + return SUCCESS; + } + + if (pIrlapCb->CRBit == CRBit) // should be opposite of mine + { + if (pIrlapCb->StationType == PRIMARY) + { + if (pIrlapCb->State == P_XMIT) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->PollTimer); + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + } + RetOnErr(StationConflict(pIrlapCb)); + pIrlapCb->State = NDM; + + return SUCCESS; + } + + if (pIrlapCb->StationType == PRIMARY) // I'm PRIMARY, this is a + { // response from secondary + switch (pIrlapCb->State) + { + case P_DISCONNECT_PEND: + if (PFBit == IRLAP_PFBIT_CLEAR) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(SendDISC(pIrlapCb)); + pIrlapCb->RetryCnt = 0; + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(GotoPCloseState(pIrlapCb)); + } + break; + + case P_CLOSE: + if (PFBit == IRLAP_PFBIT_CLEAR) + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->FinalTimer); + RetOnErr(ResendDISC(pIrlapCb)); + if (pIrlapCb->State != NDM) + { + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + } + break; + + case S_CLOSE: + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + } + else + { + switch (pIrlapCb->State) + { + case S_DISCONNECT_PEND: + if (IRLAP_PFBIT_SET == PFBit) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(SendRD(pIrlapCb)); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + pIrlapCb->State = S_CLOSE; + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + } + break; + + case S_ERROR: + if (IRLAP_PFBIT_SET == PFBit) + { + RetOnErr(SendFRMR(pIrlapCb, &FrmRejFormat)); + pIrlapCb->State = S_NRM; + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + break; + + case S_CLOSE: + if (IRLAP_PFBIT_SET == PFBit) + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + RetOnErr(SendRD(pIrlapCb)); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + else + { + IRLAP_TimerStop(pIrlapCb, &pIrlapCb->WDogTimer); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignore in this state"))); + } + } + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | StationConflict | Sends disconnect due to receipt of +* by primary of frame with Poll +* +* @rdesc SUCCESS otherwise one of the following errors: +* @flag val | desc +* +* @comm +* comments +*/ +UINT +StationConflict(PIRLAP_CB pIrlapCb) +{ + InitializeState(pIrlapCb, PRIMARY); // Primary doesn't mean anything here + + RetOnErr(ApplyDefaultParms(pIrlapCb)); + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_PRIMARY_CONFLICT; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + + return SUCCESS; +} +/***************************************************************************** +* +* @func UINT | ApplyDefaultParms | Apply default parameters and +* reinitalize MAC +* +* @rdesc SUCCESS otherwise one of the following errors: +* @flag val | desc +* +*/ +UINT +ApplyDefaultParms(PIRLAP_CB pIrlapCb) +{ + pIrlapCb->Baud = IRLAP_DEFAULT_BAUD; + + pIrlapCb->RemoteMaxTAT = IRLAP_DEFAULT_MAX_TAT; + + pIrlapCb->RemoteDataSize = IRLAP_DEFAULT_DATA_SIZE; + + pIrlapCb->RemoteWinSize = IRLAP_DEFAULT_WIN_SIZE; + + pIrlapCb->RemoteNumBOFS = IRLAP_DEFAULT_BOFS; + + pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR; + + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_RECONFIG_LINK; + IMsg.IRDA_MSG_Baud = IRLAP_DEFAULT_BAUD; + IMsg.IRDA_MSG_NumBOFs = IRLAP_DEFAULT_BOFS; + IMsg.IRDA_MSG_DataSize = IRLAP_DEFAULT_DATA_SIZE; + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ - reconfig link"))); + + return (IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg)); +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +ResendDISC(PIRLAP_CB pIrlapCb) +{ + if (pIrlapCb->RetryCnt >= pIrlapCb->N3) + { + RetOnErr(ApplyDefaultParms(pIrlapCb)); + pIrlapCb->RetryCnt = 0; + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE; + RetOnErr(IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg)); + pIrlapCb->State = NDM; + } + else + { + RetOnErr(SendDISC(pIrlapCb)); + pIrlapCb->RetryCnt++; + } + return SUCCESS; +} + +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +BOOL +IgnoreState(PIRLAP_CB pIrlapCb) +{ + switch (pIrlapCb->State) + { + case NDM: + case DSCV_MEDIA_SENSE: + case DSCV_QUERY: + case DSCV_REPLY: + case CONN_MEDIA_SENSE: + case SNRM_SENT: + case BACKOFF_WAIT: + case SNRM_RECEIVED: + case P_XMIT: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state"))); + return TRUE; + } + return FALSE; +} + +VOID +QueryTimerExp(PVOID Context) +{ + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + + IRLAP_LOG_START((pIrlapCb, "Query timer expired")); + + if (pIrlapCb->State == DSCV_REPLY) + { + pIrlapCb->State = NDM; + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Ignoring QueryTimer Expriation in state %s"), + IRLAP_StateStr[pIrlapCb->State])); + } + + IRLAP_LOG_COMPLETE(pIrlapCb); + + return; +} + +VOID +SlotTimerExp(PVOID Context) +{ + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + + IRLAP_LOG_START((pIrlapCb, "Slot timer expired")); + + if (pIrlapCb->State == DSCV_QUERY) + { + pIrlapCb->SlotCnt++; + SendDscvXIDCmd(pIrlapCb); + if (pIrlapCb->SlotCnt < pIrlapCb->MaxSlot) + { + IMsg.Prim = MAC_CONTROL_REQ; + IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE; + IMsg.IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME; + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (dscv sense)"))); + IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg); + } + else + { + pIrlapCb->GenNewAddr = FALSE; + + IMsg.Prim = IRLAP_DISCOVERY_CONF; + IMsg.IRDA_MSG_pDevList = &pIrlapCb->DevList; + IMsg.IRDA_MSG_DscvStatus = IRLAP_DISCOVERY_COMPLETED; + + // Change state now so IRLMP can do DISCOVERY_REQ on this thread + pIrlapCb->State = NDM; + + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + } + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring SlotTimer Expriation in state %s"), + IRLAP_StateStr[pIrlapCb->State])); + ; // maybe return bad state ??? + } + IRLAP_LOG_COMPLETE(pIrlapCb); + return; +} + +VOID +FinalTimerExp(PVOID Context) +{ + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + + IRLAP_LOG_START((pIrlapCb, "Final timer expired")); + + pIrlapCb->NoResponse = TRUE; + + switch (pIrlapCb->State) + { + case SNRM_SENT: + if (pIrlapCb->RetryCnt < pIrlapCb->N3) + { + pIrlapCb->BackoffTimer.Timeout = IRLAP_BACKOFF_TIME(); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->BackoffTimer); + pIrlapCb->State = BACKOFF_WAIT; + } + else + { + ApplyDefaultParms(pIrlapCb); + + pIrlapCb->RetryCnt = 0; + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE; + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + pIrlapCb->State = NDM; + } + break; + + case P_RECV: + if (pIrlapCb->RetryCnt == pIrlapCb->N2) + { + ReturnTxMsgs(pIrlapCb); + ApplyDefaultParms(pIrlapCb); + + pIrlapCb->RetryCnt = 0; // Don't have to, do it for logger + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE; + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + pIrlapCb->State = NDM; + } + else + { + pIrlapCb->RetryCnt++; + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + SendRR_RNR(pIrlapCb); + if (pIrlapCb->RetryCnt == pIrlapCb->N1) + { + IMsg.Prim = IRLAP_STATUS_IND; + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + } + } + break; + + case P_DISCONNECT_PEND: + SendDISC(pIrlapCb); + pIrlapCb->RetryCnt = 0; + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + GotoPCloseState(pIrlapCb); + break; + + case P_CLOSE: + if (pIrlapCb->RetryCnt >= pIrlapCb->N3) + { + ApplyDefaultParms(pIrlapCb); + + pIrlapCb->RetryCnt = 0; // Don't have to, do it for logger + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE; + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + GotoNDMThenDscvOrConn(pIrlapCb); + } + else + { + pIrlapCb->RetryCnt++; + SendDISC(pIrlapCb); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + } + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring Final Expriation in state %s"), + IRLAP_StateStr[pIrlapCb->State])); + } + + IRLAP_LOG_COMPLETE(pIrlapCb); + return; +} + +VOID +PollTimerExp(PVOID Context) +{ + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + + IRLAP_LOG_START((pIrlapCb, "Poll timer expired")); + + if (pIrlapCb->State == P_XMIT) + { + SendRR_RNR(pIrlapCb); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + pIrlapCb->State = P_RECV; + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring Poll Expriation in state %s"), + IRLAP_StateStr[pIrlapCb->State])); + } + + IRLAP_LOG_COMPLETE(pIrlapCb); + return; +} + +VOID +BackoffTimerExp(PVOID Context) +{ + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + + IRLAP_LOG_START((pIrlapCb, "Backoff timer expired")); + + if (pIrlapCb->State == BACKOFF_WAIT) + { + SendSNRM(pIrlapCb, TRUE); + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->FinalTimer); + pIrlapCb->RetryCnt += 1; + pIrlapCb->State = SNRM_SENT; + } + else + { + IRLAP_LOG_ACTION((pIrlapCb, + TEXT("Ignoring BackoffTimer Expriation in this state "))); + } + IRLAP_LOG_COMPLETE(pIrlapCb); + return; +} + +VOID +WDogTimerExp(PVOID Context) +{ + PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context; + + IRLAP_LOG_START((pIrlapCb, "WDog timer expired")); + + pIrlapCb->NoResponse = TRUE; + + switch (pIrlapCb->State) + { + case S_DISCONNECT_PEND: + case S_NRM: + pIrlapCb->WDogExpCnt++; + // Disconnect/threshold time is in seconds + if (pIrlapCb->WDogExpCnt * (int)pIrlapCb->WDogTimer.Timeout >= + pIrlapCb->DisconnectTime * 1000) + { + ReturnTxMsgs(pIrlapCb); + ApplyDefaultParms(pIrlapCb); + + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE; + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + pIrlapCb->State = NDM; + } + else + { + if ((pIrlapCb->WDogExpCnt * (int) pIrlapCb->WDogTimer.Timeout >= + pIrlapCb->ThresholdTime * 1000) && !pIrlapCb->StatusSent) + { + IMsg.Prim = IRLAP_STATUS_IND; + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + pIrlapCb->StatusSent = TRUE; + } + IRLAP_TimerStart(pIrlapCb, &pIrlapCb->WDogTimer); + } + break; + + case S_CLOSE: + ApplyDefaultParms(pIrlapCb); + + IMsg.Prim = IRLAP_DISCONNECT_IND; + IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE; + IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg); + pIrlapCb->State = NDM; + break; + + default: + IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignore WDogTimer expiration in state %s"), + IRLAP_StateStr[pIrlapCb->State])); + } + IRLAP_LOG_COMPLETE(pIrlapCb); + return; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +UINT +DequeMsgList(IRDA_MSG_LIST *pList, IRDA_MSG **ppMsg) +{ + if (pList->Len != 0) + { + *ppMsg = (IRDA_MSG *) RemoveHeadList(&pList->ListHead); +/** + { + IRDA_MSG *pAMsg = pList->ListHead.Flink; + + printf(TEXT("\nDEQUE: %x\n"), *ppMsg); + + while (pAMsg != &(pList->ListHead)) + { + printf(TEXT("%x->"),pAMsg); + pAMsg = pAMsg->Linkage.Flink; + } + printf(TEXT("\n")); + } +**/ + pList->Len--; + return SUCCESS; + } + return IRLAP_MSG_LIST_EMPTY; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* + + +* @ex +* example +*/ +UINT +EnqueMsgList(IRDA_MSG_LIST *pList, IRDA_MSG *pMsg, int MaxLen) +{ + if (MaxLen == -1 || pList->Len < MaxLen) + { + InsertTailList(&pList->ListHead, &(pMsg->Linkage)); + pList->Len++; +/** + { + IRDA_MSG *pAMsg = pList->ListHead.Flink; + + printf(TEXT("\nENQUE: %x\n"), pMsg); + while (pAMsg != &(pList->ListHead)) + { + printf(TEXT("%x->"),pAMsg); + pAMsg = pAMsg->Linkage.Flink; + } + printf(TEXT("\n")); + } +**/ + return SUCCESS; + } + return IRLAP_MSG_LIST_FULL; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +void +InitMsgList(IRDA_MSG_LIST *pList) +{ + InitializeListHead(&pList->ListHead); + pList->Len = 0; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc return desc +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +* +* @ex +* example +*/ +/* !!! +void +IRLAP_PrintState() +{ +#ifdef DEBUG + DEBUGMSG(1, (TEXT("IRLAP State %s\n"), IRLAP_StateStr[pIrlapCb->State])); +#else + DEBUGMSG(1, (TEXT("IRLAP State %d\n"), pIrlapCb->State)); +#endif + DEBUGMSG(1, + (TEXT(" Vs=%d Vr=%d RxWin(%d,%d) TxWin(%d,%d) TxMsgListLen=%d RxMsgFreeListLen=%d\r\n"), + pIrlapCb->Vs, pIrlapCb->Vr, + pIrlapCb->RxWin.Start, pIrlapCb->RxWin.End, + pIrlapCb->TxWin.Start, pIrlapCb->TxWin.End, + pIrlapCb->TxMsgList.Len, pIrlapCb->RxMsgFreeList.Len)); + +#ifdef TEMPERAMENTAL_SERIAL_DRIVER + DEBUGMSG(1, (TEXT(" Tossed duplicates %d\n"), TossedDups)); +#endif + + IRMAC_PrintState(); + + return; +} +*/ +int +GetMyDevAddr(BOOL New) +{ +#ifdef PEG + HKEY hKey; + LONG hRes; + TCHAR KeyName[32]; +#endif + int DevAddr, NewDevAddr; + DWORD RegDevAddr = 0; + TCHAR ValName[] = TEXT("DevAddr"); + LARGE_INTEGER li; + + KeQueryTickCount(&li); + + NewDevAddr = (int) li.LowPart; + + // Get the device address from the registry. If the key exists and the + // value is 0, store a new random address. If no key, then return + // a random address. +#ifdef PEG + _tcscpy (KeyName, COMM_REG_KEY); + _tcscat (KeyName, TEXT("IrDA")); + + hRes = RegOpenKeyEx (HKEY_LOCAL_MACHINE, KeyName, 0, 0, &hKey); + + if (hRes == ERROR_SUCCESS && + GetRegDWORDValue(hKey, ValName, &RegDevAddr)) + { + if (RegDevAddr == 0) + { + RegDevAddr = KeQueryTickCount(); + SetRegDWORDValue(hKey, ValName, RegDevAddr); + } + RegCloseKey(hKey); + + DevAddr = (int) RegDevAddr; + } +#else + DevAddr = NewDevAddr; +#endif + return DevAddr; +} + diff --git a/private/ntos/tdi/irda/irlap/irlapio.c b/private/ntos/tdi/irda/irlap/irlapio.c new file mode 100644 index 000000000..0c4a8361d --- /dev/null +++ b/private/ntos/tdi/irda/irlap/irlapio.c @@ -0,0 +1,900 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irlapio.c +* +* Description: IRLAP I/O routines +* +* Author: mbert +* +* Date: 4/25/95 +* +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +extern BYTE IRLAP_BroadcastDevAddr[]; + +// The largest MAC message is the XID Frame consisting of address, +// control, XID Format ID, XID format, + Discovery Information +#define _MAC_MSG_LEN 3+sizeof(IRLAP_XID_DSCV_FORMAT)+IRLAP_DSCV_INFO_LEN + +//static BYTE IRLAP_MAC_MsgData[_MAC_MSG_LEN]; +//static IRDA_MSG MAC_Message; +//static PIRDA_MSG pMACMsg = &MAC_Message; + +UINT +SendFrame(PIRLAP_CB, PIRDA_MSG ); + +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +*/ +UINT +ClearRxWindow(PIRLAP_CB pIrlapCb) +{ + UINT i, rc; + + // Remove everything from Rx window + for (i = pIrlapCb->Vr; i != pIrlapCb->RxWin.End; i = (i+1) % IRLAP_MOD) + { + if (pIrlapCb->RxWin.pMsg[i] != NULL) + { + /* !!! fix this OH SHIT + if((rc = EnqueMsgList(&pIrlapCb->RxMsgFreeList, + pIrlapCb->RxWin.pMsg[i], + pIrlapCb->MaxRxMsgFreeListLen)) != SUCCESS) + { + return rc; + } + */ + pIrlapCb->RxWin.pMsg[i] = NULL; + } + pIrlapCb->RxWin.End = pIrlapCb->Vr; + } + return SUCCESS; +} +/***************************************************************************** +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +*/ +UINT +SendDscvXIDCmd(PIRLAP_CB pIrlapCb) +{ + UINT rc = SUCCESS; + IRLAP_XID_DSCV_FORMAT XIDFormat; + CHAR *DscvInfo; + int DscvInfoLen; + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + memcpy(XIDFormat.SrcAddr, pIrlapCb->LocalDevice.DevAddr, IRDA_DEV_ADDR_LEN); + memcpy(XIDFormat.DestAddr, IRLAP_BroadcastDevAddr, IRDA_DEV_ADDR_LEN); + + XIDFormat.NoOfSlots = IRLAP_SLOT_FLAG(pIrlapCb->MaxSlot); + XIDFormat.GenNewAddr = pIrlapCb->GenNewAddr; + XIDFormat.Reserved = 0; + + if (pIrlapCb->SlotCnt == pIrlapCb->MaxSlot) + { + DscvInfo = pIrlapCb->LocalDevice.DscvInfo; + DscvInfoLen = pIrlapCb->LocalDevice.DscvInfoLen; + XIDFormat.SlotNo = IRLAP_END_DSCV_SLOT_NO; + } + else + { + DscvInfo = NULL; + DscvInfoLen = 0; + XIDFormat.SlotNo = pIrlapCb->SlotCnt; + } + XIDFormat.Version = pIrlapCb->LocalDevice.IRLAP_Version; + + pIMsg->IRDA_MSG_pWrite = Format_DscvXID(pIMsg, + IRLAP_BROADCAST_CONN_ADDR, + IRLAP_CMD, IRLAP_PFBIT_SET, + &XIDFormat, DscvInfo, + DscvInfoLen); + return SendFrame(pIrlapCb, pIMsg); +} +/****************************************************************************S* +* +* @func ret_type | func_name | funcdesc +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm data_type | parm_name | description +* +* @comm +* comments +*/ +UINT +SendDscvXIDRsp(PIRLAP_CB pIrlapCb) +{ + UINT rc = SUCCESS; + IRLAP_XID_DSCV_FORMAT XIDFormat; + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + XIDFormat.GenNewAddr = pIrlapCb->GenNewAddr; + if (pIrlapCb->GenNewAddr) + { + StoreULAddr(pIrlapCb->LocalDevice.DevAddr, GetMyDevAddr(TRUE)); + pIrlapCb->GenNewAddr = FALSE; + } + memcpy(XIDFormat.SrcAddr, pIrlapCb->LocalDevice.DevAddr, IRDA_DEV_ADDR_LEN); + memcpy(XIDFormat.DestAddr, pIrlapCb->RemoteDevice.DevAddr, IRDA_DEV_ADDR_LEN); + XIDFormat.NoOfSlots = IRLAP_SLOT_FLAG(pIrlapCb->RemoteMaxSlot); + XIDFormat.Reserved = 0; + XIDFormat.SlotNo = pIrlapCb->RespSlot; + XIDFormat.Version = pIrlapCb->LocalDevice.IRLAP_Version; + + pIMsg->IRDA_MSG_pWrite = Format_DscvXID(pIMsg, + IRLAP_BROADCAST_CONN_ADDR, + IRLAP_RSP, IRLAP_PFBIT_SET, + &XIDFormat, + pIrlapCb->LocalDevice.DscvInfo, + pIrlapCb->LocalDevice.DscvInfoLen); + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendSNRM | formats a SNRM frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm BYTE | ConnAddr | Connection address +* +* @comm +* The ConnAddr can be different than that in the control block. +* For reset, its the same, but set to broadcast for initial +* connection. +*/ +UINT +SendSNRM(PIRLAP_CB pIrlapCb, BOOL SendQos) +{ + IRDA_QOS_PARMS *pQos = NULL; + int ConnAddr = pIrlapCb->ConnAddr; + IRDA_MSG *pIMsg; + + if (SendQos) + { + ConnAddr = IRLAP_BROADCAST_CONN_ADDR; + pQos = &pIrlapCb->LocalQos; + } + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_SNRM(pIMsg, ConnAddr, + IRLAP_CMD, + IRLAP_PFBIT_SET, + pIrlapCb->LocalDevice.DevAddr, + pIrlapCb->RemoteDevice.DevAddr, + pIrlapCb->ConnAddr, + pQos); + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendUA | formats a UA frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm BOOL | SendQos | Send the Qos +* +* @comm +* comments +*/ +UINT +SendUA(PIRLAP_CB pIrlapCb, BOOL SendQos) +{ + IRDA_QOS_PARMS NegQos; + IRDA_QOS_PARMS *pNegQos = NULL; + BYTE *pSrcAddr = NULL; + BYTE *pDestAddr = NULL; + IRDA_MSG *pIMsg; + + if (SendQos) + { + // Put all parms (type 0 and 1) in NegQos + memcpy(&NegQos, &pIrlapCb->LocalQos, sizeof(IRDA_QOS_PARMS)); + // Overwrite type 0 parameters that have already been negotiated + NegQos.bfBaud = pIrlapCb->NegotiatedQos.bfBaud; + NegQos.bfDisconnectTime = pIrlapCb->NegotiatedQos.bfDisconnectTime; + pNegQos = &NegQos; + } + + // This will be moved into the "if" above when the spec is clarified + pSrcAddr = pIrlapCb->LocalDevice.DevAddr; + pDestAddr = pIrlapCb->RemoteDevice.DevAddr; + //------------------------------------------------------------------ + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_UA(pIMsg, + pIrlapCb->ConnAddr, + IRLAP_RSP, + IRLAP_PFBIT_SET, + pSrcAddr, pDestAddr, pNegQos); + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendDM | formats a DM frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* +* @comm +* comments +*/ +UINT +SendDM(PIRLAP_CB pIrlapCb) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_DM(pIMsg, + pIrlapCb->ConnAddr, + IRLAP_RSP, + IRLAP_PFBIT_SET); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendRD | formats a RD frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* +* @comm +* comments +*/ +UINT +SendRD(PIRLAP_CB pIrlapCb) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_RD(pIMsg, + pIrlapCb->ConnAddr, + IRLAP_RSP, + IRLAP_PFBIT_SET); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendRR | formats a RR frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* +* @comm +* comments +*/ +UINT +SendRR(PIRLAP_CB pIrlapCb) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + ClearRxWindow(pIrlapCb); + + pIrlapCb->RxWin.Start = pIrlapCb->Vr; // RxWin.Start = what we've acked + + pIMsg->IRDA_MSG_pWrite = Format_RR(pIMsg, pIrlapCb->ConnAddr, + pIrlapCb->CRBit, IRLAP_PFBIT_SET, + pIrlapCb->Vr); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendRNR | formats a RNR frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* +* @comm +* comments +*/ +UINT +SendRR_RNR(PIRLAP_CB pIrlapCb) +{ + IRDA_MSG *pIMsg; + + BYTE *(*pFormatRR_RNR)(); + + if (pIrlapCb->LocalBusy) + { + pFormatRR_RNR = Format_RNR; + } + else + { + pFormatRR_RNR = Format_RR; + } + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + ClearRxWindow(pIrlapCb); + + + pIrlapCb->RxWin.Start = pIrlapCb->Vr; // RxWin.Start = what we've acked + + + pIMsg->IRDA_MSG_pWrite = (*pFormatRR_RNR)(pIMsg, pIrlapCb->ConnAddr, + pIrlapCb->CRBit, IRLAP_PFBIT_SET, + pIrlapCb->Vr); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendDISC | formats a DISC frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* +* @comm +* comments +*/ +UINT +SendDISC(PIRLAP_CB pIrlapCb) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_DISC(pIMsg, pIrlapCb->ConnAddr, + IRLAP_CMD, IRLAP_PFBIT_SET); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendRNRM | formats a RNRM frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* +* @comm +* comments +*/ +UINT +SendRNRM(PIRLAP_CB pIrlapCb) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_RNRM(pIMsg, pIrlapCb->ConnAddr, + IRLAP_RSP, IRLAP_PFBIT_SET); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendREJ | formats a REJ frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* +* @comm +* comments +*/ +UINT +SendREJ(PIRLAP_CB pIrlapCb) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + ClearRxWindow(pIrlapCb); + + pIrlapCb->RxWin.Start = pIrlapCb->Vr; // RxWin.Start = what we've acked + + pIMsg->IRDA_MSG_pWrite = Format_REJ(pIMsg, pIrlapCb->ConnAddr, + pIrlapCb->CRBit, IRLAP_PFBIT_SET, + pIrlapCb->Vr); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendSREJ | formats a SREJ frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm int | Nr | Nr to be placed in SREJ frame +* +* @comm +* comments +*/ +UINT +SendSREJ(PIRLAP_CB pIrlapCb, int Nr) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_SREJ(pIMsg, pIrlapCb->ConnAddr, + pIrlapCb->CRBit, IRLAP_PFBIT_SET, Nr); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendFRMR | formats a FRMR frame and sends it +* +* @rdesc SUCCESS, otherwise one of the following errors: +* @flag val | desc +* +* @parm int | Nr | Nr to be placed in SREJ frame +* +* @comm +* comments +*/ +UINT +SendFRMR(PIRLAP_CB pIrlapCb, IRLAP_FRMR_FORMAT *pFRMRFormat) +{ + IRDA_MSG *pIMsg; + + pIMsg = AllocMacIMsg(pIrlapCb->pIrdaLinkCb); + + pIMsg->IRDA_MSG_pWrite = Format_FRMR(pIMsg, pIrlapCb->ConnAddr, + pIrlapCb->CRBit, IRLAP_PFBIT_SET, + pFRMRFormat); + + return SendFrame(pIrlapCb, pIMsg); +} +/***************************************************************************** +* +* @func UINT | SendIFrame | Builds and sends an I frame to MAC +* +* @rdesc SUCCESS otherwise one of the following errors: +* @flag val | desc +* +* @parm | | +* +* @comm +* comments +*/ +UINT +SendIFrame(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg, int Ns, int PFBit) +{ + UINT rc; + + if (NULL == pMsg) + { + return IRLAP_NULL_MSG; + } + + ClearRxWindow(pIrlapCb); + + pIrlapCb->RxWin.Start = pIrlapCb->Vr; // RxWin.Start = what we've acked + + (void) Format_I(pMsg, pIrlapCb->ConnAddr, pIrlapCb->CRBit, PFBit, + pIrlapCb->Vr, Ns); + + rc = SendFrame(pIrlapCb, pMsg); + + pMsg->IRDA_MSG_pHdrRead +=2; // uglyness.. chop header in case frame + // requires retransmission + return rc; +} +/***************************************************************************** +* +* @func UINT | SendUIFrame | Builds and sends an UI frame to MAC +* +* @rdesc SUCCESS otherwise one of the following errors: +* @flag val | desc +* +* @parm | | +* +* @comm +* comments +*/ +UINT +SendUIFrame(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg) +{ + if (NULL == pMsg) + { + return IRLAP_NULL_MSG; + } + (void) Format_UI(pMsg, pIrlapCb->ConnAddr, pIrlapCb->CRBit,IRLAP_PFBIT_SET); + + return SendFrame(pIrlapCb, pMsg); +} +/***************************************************************************** +* +* @func UINT | SendFrame | Builds and sends an Unnumbered frame to MAC +* +* @rdesc SUCCESS otherwise one of the following errors: +* @flag val | desc +* +* @comm +* comments +*/ +UINT +SendFrame(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg) +{ + UINT rc = SUCCESS; + + pMsg->Prim = MAC_DATA_REQ; + + rc = IrmacDown(pIrlapCb->pIrdaLinkCb, pMsg); + + IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_DATA_REQ: %s"), FrameToStr(pMsg))); + + return rc; +} +/***************************************************************************** +* +* @func UINT | _IRLMP_Up | Adds logging to the IRLMP_Up +* +* @rdesc returns of IRLMP_Up +* +* @parm PIRDA_MSG | pMsg | pointer to IRDA message +* +* @comm +* comments +*/ +/* +UINT +_IRLMP_Up(PIRDA_MSG pMsg) +{ + IRLAP_LOG_ACTION((TEXT("%s%s"), IRDA_PrimStr[pMsg->Prim], + pMsg->Prim == IRLAP_DISCOVERY_CONF ? + IRDA_StatStr[pMsg->IRDA_MSG_DscvStatus] : + pMsg->Prim == IRLAP_CONNECT_CONF ? + IRDA_StatStr[pMsg->IRDA_MSG_ConnStatus] : + pMsg->Prim == IRLAP_DISCONNECT_IND ? + IRDA_StatStr[pMsg->IRDA_MSG_DiscStatus] : + pMsg->Prim == IRLAP_DATA_CONF || pMsg->Prim == IRLAP_UDATA_CONF ? + IRDA_StatStr[pMsg->IRDA_MSG_DataStatus] : TEXT(""))); + + return (IRLMP_Up(pMsg)); +} +*/ + +BYTE * +BuildTuple(BYTE *pBuf, BYTE Pi, UINT BitField) +{ + *pBuf++ = Pi; + + if (BitField > 0xFF) + { + *pBuf++ = 2; // Pl + *pBuf++ = (BYTE) (BitField >> 8); + *pBuf++ = (BYTE) (BitField); + } + else + { + *pBuf++ = 1; // Pl + *pBuf++ = (BYTE) (BitField); + } + return pBuf; +} + +BYTE * +BuildNegParms(BYTE *pBuf, IRDA_QOS_PARMS *pQos) +{ + pBuf = BuildTuple(pBuf, QOS_PI_BAUD, pQos->bfBaud); + pBuf = BuildTuple(pBuf, QOS_PI_MAX_TAT, pQos->bfMaxTurnTime); + pBuf = BuildTuple(pBuf, QOS_PI_DATA_SZ, pQos->bfDataSize); + pBuf = BuildTuple(pBuf, QOS_PI_WIN_SZ, pQos->bfWindowSize); + pBuf = BuildTuple(pBuf, QOS_PI_BOFS, pQos->bfBofs); + pBuf = BuildTuple(pBuf, QOS_PI_MIN_TAT, pQos->bfMinTurnTime); + pBuf = BuildTuple(pBuf, QOS_PI_DISC_THRESH, pQos->bfDisconnectTime); + + return pBuf; +} + +void +StoreULAddr(BYTE Addr[], ULONG ULAddr) +{ + Addr[0] = (BYTE) ( 0xFF & ULAddr); + Addr[1] = (BYTE) ((0xFF00 & ULAddr) >> 8); + Addr[2] = (BYTE) ((0xFF0000 & ULAddr) >> 16); + Addr[3] = (BYTE) ((0xFF000000 & ULAddr) >> 24); +} + +BYTE * +_PutAddr(BYTE *pBuf, BYTE Addr[]) +{ + *pBuf++ = Addr[0]; + *pBuf++ = Addr[1]; + *pBuf++ = Addr[2]; + *pBuf++ = Addr[3]; + + return (pBuf); +} + +void +BuildUHdr(IRDA_MSG *pMsg, int FrameType, int Addr, int CRBit, int PFBit) +{ + if (pMsg->IRDA_MSG_pHdrRead != NULL) + { + pMsg->IRDA_MSG_pHdrRead -= 2; + + ASSERT(pMsg->IRDA_MSG_pHdrRead >= pMsg->IRDA_MSG_Header); + + *(pMsg->IRDA_MSG_pHdrRead) = (BYTE) _MAKE_ADDR(Addr, CRBit); + *(pMsg->IRDA_MSG_pHdrRead+1) = (BYTE) _MAKE_UCNTL(FrameType, PFBit); + } + else + { + pMsg->IRDA_MSG_pRead -= 2; + *(pMsg->IRDA_MSG_pRead) = (BYTE) _MAKE_ADDR(Addr, CRBit); + *(pMsg->IRDA_MSG_pRead+1) = (BYTE) _MAKE_UCNTL(FrameType, PFBit); + } + return; +} + +void +BuildSHdr(IRDA_MSG *pMsg, int FrameType, int Addr, int CRBit, int PFBit, int Nr) +{ + if (pMsg->IRDA_MSG_pHdrRead != NULL) + { + pMsg->IRDA_MSG_pHdrRead -= 2; + + ASSERT(pMsg->IRDA_MSG_pHdrRead >= pMsg->IRDA_MSG_Header); + + *(pMsg->IRDA_MSG_pHdrRead) = (BYTE) _MAKE_ADDR(Addr, CRBit); + *(pMsg->IRDA_MSG_pHdrRead+1) = (BYTE) _MAKE_SCNTL(FrameType, PFBit, Nr); + } + else + { + pMsg->IRDA_MSG_pRead -= 2; + *(pMsg->IRDA_MSG_pRead) = (BYTE) _MAKE_ADDR(Addr, CRBit); + *(pMsg->IRDA_MSG_pRead+1) = (BYTE) _MAKE_SCNTL(FrameType, PFBit, Nr); + } + return; +} + +BYTE * +Format_SNRM(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, BYTE SAddr[], + BYTE DAddr[], int CAddr, IRDA_QOS_PARMS *pQos) +{ + BuildUHdr(pMsg, IRLAP_SNRM, Addr, CRBit, PFBit); + + if (pQos != NULL) + { + pMsg->IRDA_MSG_pWrite = _PutAddr(pMsg->IRDA_MSG_pWrite, SAddr); + pMsg->IRDA_MSG_pWrite = _PutAddr(pMsg->IRDA_MSG_pWrite, DAddr); + *pMsg->IRDA_MSG_pWrite++ = CAddr << 1; // Thats what the f'n spec says + pMsg->IRDA_MSG_pWrite = BuildNegParms(pMsg->IRDA_MSG_pWrite, pQos); + } + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_DISC(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit) +{ + BuildUHdr(pMsg, IRLAP_DISC, Addr, CRBit, PFBit); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_UI(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit) +{ + BuildUHdr(pMsg, IRLAP_UI, Addr, CRBit, PFBit); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_DscvXID(IRDA_MSG *pMsg, int ConnAddr, int CRBit, int PFBit, + IRLAP_XID_DSCV_FORMAT *pXIDFormat, + CHAR DscvInfo[], int DscvInfoLen) +{ + if (pMsg->IRDA_MSG_pHdrRead != NULL) + { + pMsg->IRDA_MSG_pHdrRead -= 2; + + ASSERT(pMsg->IRDA_MSG_pHdrRead >= pMsg->IRDA_MSG_Header); + + *(pMsg->IRDA_MSG_pHdrRead) = (BYTE) _MAKE_ADDR(ConnAddr, CRBit); + if (CRBit) + *(pMsg->IRDA_MSG_pHdrRead+1)= + (BYTE) _MAKE_UCNTL(IRLAP_XID_CMD, PFBit); + else + *(pMsg->IRDA_MSG_pHdrRead+1)= + (BYTE) _MAKE_UCNTL(IRLAP_XID_RSP, PFBit); + } + else + { + pMsg->IRDA_MSG_pRead -= 2; + *(pMsg->IRDA_MSG_pRead) = (BYTE) _MAKE_ADDR(ConnAddr, CRBit); + if (CRBit) + *(pMsg->IRDA_MSG_pRead+1)= + (BYTE) _MAKE_UCNTL(IRLAP_XID_CMD, PFBit); + else + *(pMsg->IRDA_MSG_pRead+1)= + (BYTE) _MAKE_UCNTL(IRLAP_XID_RSP, PFBit); + } + + *pMsg->IRDA_MSG_pWrite++ = IRLAP_XID_DSCV_FORMAT_ID; + + memcpy(pMsg->IRDA_MSG_pWrite, (CHAR *) pXIDFormat, + sizeof(IRLAP_XID_DSCV_FORMAT) - 1); // Subtract for FirstDscvByte + // in structure + pMsg->IRDA_MSG_pWrite += sizeof(IRLAP_XID_DSCV_FORMAT) - 1; + + if (DscvInfo != NULL) + { + memcpy(pMsg->IRDA_MSG_pWrite, DscvInfo, DscvInfoLen); + pMsg->IRDA_MSG_pWrite += DscvInfoLen; + } + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_TEST(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, + BYTE SAddr[], BYTE DAddr[]) +{ + BuildUHdr(pMsg, IRLAP_TEST, Addr, CRBit, PFBit); + + pMsg->IRDA_MSG_pWrite = _PutAddr(pMsg->IRDA_MSG_pWrite, SAddr); + pMsg->IRDA_MSG_pWrite = _PutAddr(pMsg->IRDA_MSG_pWrite, DAddr); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_RNRM(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit) +{ + BuildUHdr(pMsg, IRLAP_RNRM, Addr, CRBit, PFBit); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_UA(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, BYTE SAddr[], + BYTE DAddr[], IRDA_QOS_PARMS *pQos) +{ + BuildUHdr(pMsg, IRLAP_UA, Addr, CRBit, PFBit); + + if (SAddr != NULL) + { + pMsg->IRDA_MSG_pWrite = _PutAddr(pMsg->IRDA_MSG_pWrite, SAddr); + } + if (DAddr != NULL) + { + pMsg->IRDA_MSG_pWrite = _PutAddr(pMsg->IRDA_MSG_pWrite, DAddr); + } + + if (pQos != NULL) + pMsg->IRDA_MSG_pWrite = BuildNegParms(pMsg->IRDA_MSG_pWrite, pQos); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_FRMR(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, + IRLAP_FRMR_FORMAT *pFormat) +{ + BuildUHdr(pMsg, IRLAP_FRMR, Addr, CRBit, PFBit); + + memcpy(pMsg->IRDA_MSG_pWrite, (CHAR *)pFormat,sizeof(IRLAP_FRMR_FORMAT)); + pMsg->IRDA_MSG_pWrite += sizeof(IRLAP_FRMR_FORMAT); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_DM(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit) +{ + BuildUHdr(pMsg, IRLAP_DM, Addr, CRBit, PFBit); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_RD(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit) +{ + BuildUHdr(pMsg, IRLAP_RD, Addr, CRBit, PFBit); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_RR(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr) +{ + BuildSHdr(pMsg, IRLAP_RR, Addr, CRBit, PFBit, Nr); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_RNR(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr) +{ + BuildSHdr(pMsg, IRLAP_RNR, Addr, CRBit, PFBit, Nr); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_REJ(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr) +{ + BuildSHdr(pMsg, IRLAP_REJ, Addr, CRBit, PFBit, Nr); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_SREJ(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr) +{ + BuildSHdr(pMsg, IRLAP_SREJ, Addr, CRBit, PFBit, Nr); + + return (pMsg->IRDA_MSG_pWrite); +} + +BYTE * +Format_I(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr, int Ns) +{ + if (pMsg->IRDA_MSG_pHdrRead != NULL) + { + pMsg->IRDA_MSG_pHdrRead -= 2; + + ASSERT(pMsg->IRDA_MSG_pHdrRead >= pMsg->IRDA_MSG_Header); + + *(pMsg->IRDA_MSG_pHdrRead) = (BYTE) _MAKE_ADDR(Addr, CRBit); + *(pMsg->IRDA_MSG_pHdrRead+1) = (BYTE) (((Ns & 7) << 1) + + ((PFBit & 1)<< 4) + (Nr <<5)); + } + else + { + pMsg->IRDA_MSG_pRead -= 2; + *(pMsg->IRDA_MSG_pRead) = (BYTE) _MAKE_ADDR(Addr, CRBit); + *(pMsg->IRDA_MSG_pRead+1) = (BYTE) (((Ns & 7) << 1) + + ((PFBit & 1)<< 4) + (Nr <<5)); + } + return (pMsg->IRDA_MSG_pWrite); +} + + +// TEMP +UINT IrlmpUp(PVOID IrlmpContext, PIRDA_MSG pIMsg) +{ + return 0; +} diff --git a/private/ntos/tdi/irda/irlap/irlapio.h b/private/ntos/tdi/irda/irlap/irlapio.h new file mode 100644 index 000000000..f65d390eb --- /dev/null +++ b/private/ntos/tdi/irda/irlap/irlapio.h @@ -0,0 +1,32 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irlapio.h +* +* Description: prototypes for IRLAP I/O routines +* +* Author: mbert +* +* Date: 4/25/95 +* +*/ +void SetMsgPointers(PIRLAP_CB, PIRDA_MSG); +UINT SendDscvXIDCmd(PIRLAP_CB); +UINT SendDscvXIDRsp(PIRLAP_CB); +UINT SendSNRM(PIRLAP_CB, BOOL); +UINT SendUA(PIRLAP_CB, BOOL); +UINT SendDM(PIRLAP_CB); +UINT SendRD(PIRLAP_CB); +UINT SendRR(PIRLAP_CB); +UINT SendRR_RNR(PIRLAP_CB); +UINT SendDISC(PIRLAP_CB); +UINT SendRNRM(PIRLAP_CB); +UINT SendIFrame(PIRLAP_CB, PIRDA_MSG, int, int); +UINT SendSREJ(PIRLAP_CB, int); +UINT SendREJ(PIRLAP_CB); +UINT SendFRMR(PIRLAP_CB, IRLAP_FRMR_FORMAT *); +UINT SendUIFrame(PIRLAP_CB, PIRDA_MSG); +UINT SendFrame(PIRLAP_CB, PIRDA_MSG); +UINT _IRLMP_Up(PIRDA_MSG); + diff --git a/private/ntos/tdi/irda/irlap/irlaplog.c b/private/ntos/tdi/irda/irlap/irlaplog.c new file mode 100644 index 000000000..ae95fa8c0 --- /dev/null +++ b/private/ntos/tdi/irda/irlap/irlaplog.c @@ -0,0 +1,265 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irlaplog.c +* +* Description: IRLAP state machine logging and errors +* +* Author: mbert +* +* Date: 4/15/95 +* +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _IRLAPLOG_C_ + +#ifdef DEBUG + + +TCHAR *DecodeIRDA(int *pFrameType,// returned frame type (-1=bad frame) + BYTE *pFrameBuf, // pointer to buffer containing IRLAP frame + UINT FrameLen, // length of buffer + TCHAR *pOutStr, // string where decoded packet is placed + UINT DecodeLayer,// 1,LAP only, 2 LAP/LMP, 3, LAP/LMP/TTP + BOOL fNoConnAddr,// TRUE->Don't show connection address in str + int DispMode ) +{ + *pOutStr = TEXT('\0'); + + return pOutStr; +} +TCHAR _ABuf[512]; + +#ifndef PEG +TCHAR _DecodeStr1[1000]; +TCHAR _DecodeStr2[1000]; +#else +TCHAR _DecodeStr1[] = TEXT("(null)"); +TCHAR _DecodeStr2[] = TEXT("(null)"); +#endif + +int _FrameType; + +int ActCnt[10]; + +int vNestedEvent = 0; + +// Keep in sync with IRLAP_STATE in irlap.h +TCHAR *IRLAP_StateStr[] = { + TEXT("NDM"), + TEXT("DSCV_MEDIA_SENSE"), + TEXT("DSCV_QUERY"), + TEXT("DSCV_REPLY"), + TEXT("CONN_MEDIA_SENSE"), + TEXT("SNRM_SENT"), + TEXT("BACKOFF_WAIT"), + TEXT("SNRM_RECEIVED"), + TEXT("P_XMIT"), + TEXT("P_RECV"), + TEXT("P_DISCONNECT_PEND"), + TEXT("P_CLOSE"), + TEXT("S_NRM"), + TEXT("S_DISCONNECT_PEND"), + TEXT("S_ERROR"), + TEXT("S_CLOSE") +}; + +// Keep in sync with IRDA_SERVICE_PRIM in irda.h +TCHAR *IRDA_PrimStr[] = +{ + TEXT("MAC_DATA_REQ"), + TEXT("MAC_DATA_IND"), + TEXT("MAC_CONTROL_REQ"), + TEXT("MAC_CONTROL_CONF"), + TEXT("IRLAP_DISCOVERY_REQ"), + TEXT("IRLAP_DISCOVERY_IND"), + TEXT("IRLAP_DISCOVERY_CONF"), + TEXT("IRLAP_CONNECT_REQ"), + TEXT("IRLAP_CONNECT_IND"), + TEXT("IRLAP_CONNECT_RESP"), + TEXT("IRLAP_CONNECT_CONF"), + TEXT("IRLAP_DISCONNECT_REQ"), + TEXT("IRLAP_DISCONNECT_IND"), + TEXT("IRLAP_DATA_REQ"), + TEXT("IRLAP_DATA_IND"), + TEXT("IRLAP_DATA_CONF"), + TEXT("IRLAP_UDATA_REQ"), + TEXT("IRLAP_UDATA_IND"), + TEXT("IRLAP_UDATA_CONF"), + TEXT("IRLAP_STATUS_IND"), + TEXT("IRLAP_FLOWON_REQ"), + TEXT("IRLAP_FLOWON_IND") + TEXT("IRLMP_DISCOVERY_REQ"), + TEXT("IRLMP_DISCOVERY_CONF"), + TEXT("IRLMP_CONNECT_REQ"), + TEXT("IRLMP_CONNECT_IND"), + TEXT("IRLMP_CONNECT_RESP"), + TEXT("IRLMP_CONNECT_CONF"), + TEXT("IRLMP_DISCONNECT_REQ"), + TEXT("IRLMP_DISCONNECT_IND"), + TEXT("IRLMP_DATA_REQ"), + TEXT("IRLMP_DATA_IND"), + TEXT("IRLMP_DATA_CONF"), + TEXT("IRLMP_UDATA_REQ"), + TEXT("IRLMP_UDATA_IND"), + TEXT("IRLMP_UDATA_CONF"), + TEXT("IRLMP_ACCESSMODE_REQ"), + TEXT("IRLMP_ACCESSMODE_IND"), + TEXT("IRLMP_ACCESSMODE_CONF"), + TEXT("IRLMP_FLOWON_REQ"), + TEXT("IRLMP_FLOWON_IND") +}; + +// keep in sync with IRDA_ServiceStatus in irda.h +TCHAR *IRDA_StatStr[] = +{ + TEXT(" - MEDIA_BUSY"), + TEXT(" - MEDIA_CLEAR"), + TEXT(" - DISCOVERY_COLLISION"), + TEXT(" - REMOTE_DISCOVERY_IN_PROGRESS"), + TEXT(" - REMOTE_CONNECT_IN_PROGRSS"), + TEXT(" - DISCOVERY_COMPLETED"), + TEXT(" - REMOTE_CONNECTION_IN_PROGRESS"), + TEXT(" - CONNECTION_COMPLETED"), + TEXT(" - REMOTE_INITIATED"), + TEXT(" - PRIMARY_CONFLICT"), + TEXT(" - DISCONNECT_COMPLETE"), + TEXT(" - NO_RESPONSE"), + TEXT(" - IRLAP_DECLINE_RESET"), + TEXT(" - DATA_REQUEST_COMPLETED"), + TEXT(" - DATA_REQUEST_FAILED_LINK_RESET"), + TEXT(" - DATA_REQUEST_FAILED_REMOTE_BUSY") +}; + +// Keep in sync with MAC_CONTROL_OPERATION in irda.h +TCHAR *MAC_OpStr[] = +{ + TEXT("initialize link"), + TEXT("shutdown link"), + TEXT("reconfig link"), + TEXT("media sense") +}; + +TCHAR +*FrameToStr(IRDA_MSG *pMsg) +{ +#ifndef PEG + BYTE *ptr; + int i = 0; + int j; + TCHAR *pD1 = _DecodeStr1; + TCHAR *pD2 = _DecodeStr2; + + // copy the frame to a contiguous buffer + + ptr = pMsg->IRDA_MSG_pHdrRead; + while (ptr != pMsg->IRDA_MSG_pHdrWrite) + { + _ABuf[i++] = *ptr++; + } + ptr = pMsg->IRDA_MSG_pRead; + while (ptr != pMsg->IRDA_MSG_pWrite) + { + _ABuf[i++] = *ptr++; + } + + DecodeIRDA(&_FrameType, (char *)_ABuf, i, _DecodeStr1, 2, FALSE, 1); + + // insert spaces and break-up into multiple lines + i = 0; + do + { + if (i++%69 == 0) + { + *pD2++ = TEXT('\r'); + *pD2++ = TEXT('\n'); + for (j = 0; j<7;j++) + { + *pD2++ = TEXT(' '); + } + } + *pD2++ = *pD1++; + } while (*pD1 != TEXT('\0')); + + *pD2 = TEXT('\0'); +#endif + return (_DecodeStr2); +} +void +IRLAP_EventLogStart(PIRLAP_CB pIrlapCb, TCHAR *pFormat, ...) +{ + va_list ArgList; + + va_start (ArgList, pFormat); + + if (++vNestedEvent == 1) + { + DEBUGMSG(DBG_IRLAPLOG, (TEXT("----------------\r\n"))); + } + else + { + DEBUGMSG(DBG_IRLAPLOG, (TEXT("!!!!!!!!!!!!!!!!\r\n"))); + } + + DEBUGMSG(DBG_IRLAPLOG, (TEXT("Ev%d: "), vNestedEvent)); + + ActCnt[vNestedEvent] = 0; + + vsprintf(_ABuf, pFormat, ArgList); + DEBUGMSG(DBG_IRLAPLOG, (_ABuf)); + + DEBUGMSG(DBG_IRLAPLOG, (TEXT("\r\nStart State: %s\r\nActions:\r\n"), + IRLAP_StateStr[pIrlapCb->State])); + + va_end (ArgList); +} + +void __cdecl +IRLAP_LogAction(PIRLAP_CB pIrlapCb, TCHAR *pFormat, ...) +{ + va_list ArgList; + + va_start (ArgList, pFormat); + + DEBUGMSG(DBG_IRLAPLOG, (TEXT(" %d. "), ++ActCnt[vNestedEvent])); + + vsprintf(_ABuf, pFormat, ArgList); + DEBUGMSG(DBG_IRLAPLOG, (_ABuf)); + + DEBUGMSG(DBG_IRLAPLOG, (TEXT("\n"))); + + va_end (ArgList); +} + +#define PRINT_IF_TRUE(bool, str) (bool == TRUE ? str : TEXT("")) + +void +IRLAP_EventLogComplete(PIRLAP_CB pIrlapCb) +{ + DEBUGMSG(DBG_IRLAPLOG, + (TEXT("Vs=%d Vr=%d RxWin(%d,%d) TxWin(%d,%d) TxListLen=%d\r\n"), + pIrlapCb->Vs, pIrlapCb->Vr, + pIrlapCb->RxWin.Start, pIrlapCb->RxWin.End, + pIrlapCb->TxWin.Start, pIrlapCb->TxWin.End, + pIrlapCb->TxMsgList.Len)); + + DEBUGMSG(DBG_IRLAPLOG, (TEXT("Ev%d End St: %s\r\n"), + vNestedEvent--, IRLAP_StateStr[pIrlapCb->State])); + + if (vNestedEvent > 0) + { + DEBUGMSG(DBG_IRLAPLOG, (TEXT("!!!!!!!!!!!!!!!!\r\n"))); + } +} + +#endif diff --git a/private/ntos/tdi/irda/irlap/irlapp.h b/private/ntos/tdi/irda/irlap/irlapp.h new file mode 100644 index 000000000..bd2498263 --- /dev/null +++ b/private/ntos/tdi/irda/irlap/irlapp.h @@ -0,0 +1,299 @@ +/***************************************************************************** +* +* Copyright (c) 1995 Microsoft Corporation +* +* File: irlap.h +* +* Description: IRLAP Protocol and control block definitions +* +* Author: mbert +* +* Date: 4/15/95 +* +*/ + +#define IRLAP_MEDIA_SENSE_TIME 500 +#define IRLAP_SLOT_TIMEOUT 50 +#define IRLAP_DSCV_SENSE_TIME 30 + +// XID Format +#define IRLAP_XID_DSCV_FORMAT_ID 0x01 +#define IRLAP_XID_NEGPARMS_FORMAT_ID 0x02 +typedef struct +{ + BYTE SrcAddr[IRDA_DEV_ADDR_LEN]; + BYTE DestAddr[IRDA_DEV_ADDR_LEN]; + BYTE NoOfSlots:2; + BYTE GenNewAddr:1; + BYTE Reserved:5; + BYTE SlotNo; + BYTE Version; + BYTE FirstDscvInfoByte; +} IRLAP_XID_DSCV_FORMAT; + +// Frame Reject Format +typedef struct +{ + BYTE CntlField; + BYTE Fill1:1; + BYTE Vs:3; + BYTE CRBit:1; + BYTE Vr:3; + BYTE W:1; + BYTE X:1; + BYTE Y:1; + BYTE Z:1; + BYTE Fill2:4; +} IRLAP_FRMR_FORMAT; + +// SNRM Frame Format +typedef struct +{ + BYTE SrcAddr[IRDA_DEV_ADDR_LEN]; + BYTE DestAddr[IRDA_DEV_ADDR_LEN]; + BYTE ConnAddr; // actually shifted for CRBit -> STUPID !! + BYTE FirstQosByte; +} IRLAP_SNRM_FORMAT; + +// UA Frame Format +typedef struct +{ + BYTE SrcAddr[IRDA_DEV_ADDR_LEN]; + BYTE DestAddr[IRDA_DEV_ADDR_LEN]; + BYTE FirstQosByte; +} IRLAP_UA_FORMAT; + +#define IRLAP_MAX_TX_MSG_LIST_LEN 8 +#define IRLAP_MAX_DATA_SIZE 4096 +#define IRLAP_MAX_SLOTS 16 +#define IRLAP_DEFAULT_BAUD 9600 +#define IRLAP_DEFAULT_DATA_SIZE 64 +#define IRLAP_DEFAULT_MAX_TAT 500 +#define IRLAP_DEFAULT_BOFS 11 +#define IRLAP_DEFAULT_WIN_SIZE 1 + +// Macros for extracting various fields +#define IRLAP_GET_ADDR(addr) (addr >> 1) +#define IRLAP_GET_CRBIT(addr) (addr & 1) +#define IRLAP_GET_PFBIT(cntl) ((cntl >>4) & 1) +#define IRLAP_GET_UCNTL(cntl) (cntl & 0xEF) +#define IRLAP_GET_SCNTL(cntl) (cntl & 0x0F) +#define IRLAP_FRAME_TYPE(cntl) (cntl & 0x01 ? (cntl & 3) : 0) +#define IRLAP_GET_NR(cntl) ((cntl & 0xE0) >> 5) +#define IRLAP_GET_NS(cntl) ((cntl & 0xE) >> 1) + +// IRLAP constants +#define IRLAP_BROADCAST_CONN_ADDR 0x7F +#define IRLAP_END_DSCV_SLOT_NO 0xFF +#define IRLAP_CMD 1 +#define IRLAP_RSP 0 +#define IRLAP_PFBIT_SET 1 +#define IRLAP_PFBIT_CLEAR 0 +#define IRLAP_GEN_NEW_ADDR 1 +#define IRLAP_NO_NEW_ADDR 0 + +// Macro for creating Number of Slots of Discovery Flags Field of XID Format +// if S(Slots) <= 1 return 0, <= 6 return 1, <= 8 return 2, else return 3 +#define IRLAP_SLOT_FLAG(S) (S <= 1 ? 0 : (S <= 6 ? 1 : (S <= 8 ? 2 : 3))) + +int _inline IRLAP_RAND(int Min, int Max) +{ + LARGE_INTEGER li; + + KeQueryTickCount(&li); + + return ((li.LowPart % (Max+1-Min)) + Min); +} + +// Backoff time is a random time between 0.5 and 1.5 times the time to +// send a SNRM. _SNRM_TIME() is actually half (1000ms/2) time to send +// SNRM_LEN of characters at 9600 (9600/10 bits per char). +#define _SNRM_LEN 32 +#define _SNRM_TIME() (_SNRM_LEN*500/960) +#define IRLAP_BACKOFF_TIME() IRLAP_RAND(_SNRM_TIME(), 3*_SNRM_TIME()) + +#define QOS_PI_BAUD 0x01 +#define QOS_PI_MAX_TAT 0x82 +#define QOS_PI_DATA_SZ 0x83 +#define QOS_PI_WIN_SZ 0x84 +#define QOS_PI_BOFS 0x85 +#define QOS_PI_MIN_TAT 0x86 +#define QOS_PI_DISC_THRESH 0x08 + + +#define IRLAP_I_FRAME 0x00 +#define IRLAP_S_FRAME 0x01 +#define IRLAP_U_FRAME 0x03 + +// Unnumbered Frame types with P/F bit set to 0 +#define IRLAP_UI 0x03 +#define IRLAP_XID_CMD 0x2f +#define IRLAP_TEST 0xe3 +#define IRLAP_SNRM 0x83 +#define IRLAP_RNRM 0x83 +#define IRLAP_DISC 0x43 +#define IRLAP_RD 0x43 +#define IRLAP_UA 0x63 +#define IRLAP_FRMR 0x87 +#define IRLAP_DM 0x0f +#define IRLAP_XID_RSP 0xaf + +// Supervisory Frames +#define IRLAP_RR 0x01 +#define IRLAP_RNR 0x05 +#define IRLAP_REJ 0x09 +#define IRLAP_SREJ 0x0d + +#define _MAKE_ADDR(Addr, CRBit) ((Addr << 1) + (CRBit & 1)) +#define _MAKE_UCNTL(Cntl, PFBit) (Cntl + ((PFBit & 1)<< 4)) +#define _MAKE_SCNTL(Cntl, PFBit, Nr) (Cntl + ((PFBit & 1)<< 4) + (Nr <<5)) + +#define IRLAP_CB_SIG 0x7f2a364bUL + +// IRLAP Control Block +typedef struct +{ + IRDA_MSG *pMsg[IRLAP_MOD]; + UINT Start; + UINT End; +#ifdef TEMPERAMENTAL_SERIAL_DRIVER + int FCS[IRLAP_MOD]; +#endif +} IRLAP_WINDOW; + +typedef enum +{ + PRIMARY, + SECONDARY +} IRLAP_STN_TYPE; + +typedef enum // KEEP IN SYNC with IRLAP_StateStr in irlaplog.c +{ + NDM, // Normal Disconnect Mode + DSCV_MEDIA_SENSE, // Discovery Media Sense (Before Discovery) + DSCV_QUERY, // Discovery Query (Discovery initiated) + DSCV_REPLY, // Discovery Reply (Received DSCV XID cmd from Remote) + CONN_MEDIA_SENSE, // Connect Media Sense (Before connection estab) + SNRM_SENT, // SNRM sent - waiting for UA or DM from Remote + BACKOFF_WAIT, // Waiting random backoff before sending next SNRM + SNRM_RECEIVED, // SNRM rcvd - waiting for response from upper layer + P_XMIT, // Primary transmit + P_RECV, // Primary receive + P_DISCONNECT_PEND, // Upper layer request disconnect while in P_RECV + P_CLOSE, // Sent DISC, waiting for response + S_NRM, // Secondary Normal Response Mode XMIT/RECV + S_DISCONNECT_PEND, // Upper layer request disconnect while in S_NRM + S_ERROR, // Waiting for PF bit then send a FRMR + S_CLOSE, // Requested disconnect (RD) waiting for DISC command +} IRLAP_STATE; + +typedef struct IrlapControlBlock +{ + IRLAP_STATE State; + IRDA_DEVICE LocalDevice; + IRDA_DEVICE RemoteDevice; + PIRDA_LINK_CB pIrdaLinkCb; + IRDA_QOS_PARMS LocalQos; // QOS from LMP + IRDA_QOS_PARMS RemoteQos; // QOS of remote taken from SNRM/UA + IRDA_QOS_PARMS NegotiatedQos; // Union of remote and local QOS + int Baud; // Type 0 negotiation parm + int DisconnectTime;// Type 0 negotiation parm + int ThresholdTime; // Type 0 negotiotion parm + int LocalMaxTAT; // Type 1 negotiation parm + int LocalDataSize; // Type 1 negotiation parm + int LocalWinSize; // Type 1 negotiation parm + int LocalNumBOFS; // Type 1 negotiation parm + int RemoteMaxTAT; // Type 1 negotiation parm + int RemoteDataSize;// Type 1 negotiation parm + int RemoteWinSize; // Type 1 negotiation parm + int RemoteNumBOFS; // Type 1 negotiation parm + int RemoteMinTAT; // Type 1 negotiation parm + IRLAP_STN_TYPE StationType; // PRIMARY or SECONDARY + int ConnAddr; // Connection Address + int SNRMConnAddr; // Connection address contained in SNRM + // save it until get CONNECT_RESP + int CRBit; // Primary = 1, Secondary = 0 + int RespSlot; // Secondary. Slot to respond in + int SlotCnt; // Primary. Current slot number + int MaxSlot; // Maximum slots to send in Dscv + int RemoteMaxSlot; // Number of Dscv's remote will send + LIST_ENTRY DevList; // Discovered device list + UINT Vs; // send state variable + UINT Vr; // receive state variable + IRLAP_WINDOW RxWin; // Holds out of sequence rxd frames + IRLAP_WINDOW TxWin; // Holds unacked txd frames + IRDA_MSG_LIST TxMsgList; // DATA_REQ, UDATA_REQ queued here + int RetryCnt; // Count of number of retrans of DSCV,SNRM + int N1; // const# retries before sending status up + int N2; // const# retries before disconnecting + int N3; // const# of connection retries + IRDA_TIMER SlotTimer; + IRDA_TIMER QueryTimer; + IRDA_TIMER PollTimer; + IRDA_TIMER FinalTimer; + IRDA_TIMER WDogTimer; + IRDA_TIMER BackoffTimer; + int WDogExpCnt; // Count of WDog expirations + int StatusSent; // Status ind has been sent + CRITICAL_SECTION CS; // Control block synchronization + BOOL GenNewAddr; // Flag indicating whether to set new addr + BOOL DscvRespSent; // Secondary. Sent XID Discv response + BOOL RemoteBusy; // Remote has sent a RNR + BOOL LocalBusy; // Local busy condition, we sent RNR + BOOL ClrLocalBusy; // Send RR + BOOL LocalDiscReq; // why 2ndary got DISC + BOOL ConnAfterClose;// Conn req while in p_close + BOOL DscvAfterClose;// Dscv_req while in p_close + BOOL NoResponse; // Final/WD timer exp'd, used with RetryCnt + UINT Sig; // Signature +} IRLAP_CB, *PIRLAP_CB; + +#define LINE_CAPACITY(icb) (icb->RemoteWinSize * \ + (icb->RemoteDataSize + \ + 6+icb->RemoteNumBOFS)) + +BYTE *BuildNegParms(BYTE *pBuf, IRDA_QOS_PARMS *pQos); + +void StoreULAddr(BYTE Addr[], ULONG ULAddr); + +BYTE *Format_SNRM(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, + BYTE SAddr[], BYTE DAddr[], int CAddr, + IRDA_QOS_PARMS *pQos); + +BYTE *Format_DISC(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit); + +BYTE *Format_UI(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit); + +BYTE *Format_DscvXID(IRDA_MSG *pMsg, int ConnAddr, int CRBit, int PFBit, + IRLAP_XID_DSCV_FORMAT *pXidFormat, CHAR DscvInfo[], + int Len); + +BYTE *Format_TEST(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, + BYTE SAddr[], BYTE DAddr[]); + +BYTE *Format_RNRM(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit); + +BYTE *Format_UA(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, + BYTE SAddr[], BYTE DAddr[], IRDA_QOS_PARMS *pQos); + +BYTE *Format_FRMR(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, + IRLAP_FRMR_FORMAT *pFormat); + +BYTE *Format_DM(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit); + +BYTE *Format_RD(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit); + +BYTE *Format_RR(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr); + +BYTE *Format_RNR(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr); + +BYTE *Format_REJ(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr); + +BYTE *Format_SREJ(IRDA_MSG *pMsg, int Addr, int CRBit, int PFBit, int Nr); + +BYTE * Format_I(IRDA_MSG *pMsg, int Addr, int CRBit, + int PFBit, int Nr, int Ns); + +int GetMyDevAddr(BOOL New); + + diff --git a/private/ntos/tdi/irda/irlap/makefile b/private/ntos/tdi/irda/irlap/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/tdi/irda/irlap/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/tdi/irda/irlap/sources b/private/ntos/tdi/irda/irlap/sources new file mode 100644 index 000000000..0f1ba5b0c --- /dev/null +++ b/private/ntos/tdi/irda/irlap/sources @@ -0,0 +1,23 @@ +MAJORCOMP=ntos +MINORCOMP=irda + +NTPROFILEINPUT=yes + +TARGETNAME=irlap +TARGETTYPE=LIBRARY +TARGETPATH=..\lib +TARGETLIBS= + + +INCLUDES=..\inc;..\..\..\inc;..\..\..\..\inc; + +C_DEFINES=$(C_DEFINES) -DNT -D_NTDRIVER_ -DRASAUTODIAL -D_PNP_POWER -DSECFLTR + +MSC_WARNING_LEVEL=/W3 /WX + + +SOURCES= irlap.c \ + irlaplog.c \ + irlapio.c + + -- cgit v1.2.3