⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irlmp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*****************************************************************************
*
*
*       @doc
*       @module irlmp.c | Provides IrLMP API
*
*       Date: 4/15/95
*
*       @comm
*
*  This module exports the following API's:
*
*       IrlmpOpenLink()
*       IrlmpCloseLink()
*       IrlmpDown()
*       IrlmpUp()
*
*
*                |---------|
*                |   Tdi   |
*                |---------|
*                  /|\  |
*                   |   |
*           TdiUp() |   | IrlmpDown()
*                   |   |
*                   |  \|/
*                |---------|      IrdaTimerStart()     |-------|
*                |         |-------------------------->|       |
*                |  IRLMP  |                           | TIMER |
*                |         |<--------------------------|       |
*                |---------|      ExpFunc()            |-------|
*                  /|\  |
*                   |   |
*         IrlmpUp() |   | IrlapDown()
*                   |   |
*                   |  \|/
*                |---------|
*                |  IRLAP  |
*                |---------|
*
* See irda.h for complete message definitions
*
* Connection context for IRLMP and Tdi are exchanged
* during connection establishment:
*
*   Active connection:
*      +------------+ IRLMP_CONNECT_REQ(TdiContext)           +-------+
*      |            |---------------------------------------->|       |
*      |    Tdi     | IRLMP_CONNECT_CONF(IrlmpContext)        | IRMLP |
*      |            |<----------------------------------------|       |
*      +------------+                                         +-------+
*
*   Passive connection:
*      +------------+ IRLMP_CONNECT_IND(IrlmpContext)         +-------+
*      |            |<----------------------------------------|       |
*      |    Tdi     | IRLMP_CONNECT_RESP(TdiContext)          | IRMLP |
*      |            |---------------------------------------->|       |
*      +------------+                                         +-------+
*
*   
*   Tdi calling IrlmpDown(void *pIrlmpContext, IRDA_MSG *pMsg)
*       pIrlmpContext = NULL for the following:
*       pMsg->Prim = IRLMP_DISCOVERY_REQ,
*                    IRLMP_CONNECT_REQ,
*                    IRLMP_FLOWON_REQ,
*                    IRLMP_GETVALUEBYCLASS_REQ.
*       In all other cases, the pIRLMPContext must be a valid context.
*
*   IRLMP calling TdiUp(void *pTdiContext, IRDA_MSG *pMsg)
*       pTdiContext = NULL for the following:
*       pMsg->Prim = IRLAP_STATUS_IND,
*                    IRLMP_DISCOVERY_CONF,
*                    IRLMP_CONNECT_IND,
*                    IRLMP_GETVALUEBYCLASS_CONF.
*       In all other cases, the pTdiContext will have a valid context.
*/
#include <irda.h>
#include <irlap.h>
#include <irlmp.h>
#include <irlmpp.h>

// IAS
UCHAR IAS_IrLMPSupport[] = {IAS_IRLMP_VERSION, IAS_SUPPORT_BIT_FIELD, 
                           IAS_LMMUX_SUPPORT_BIT_FIELD};

const CHAR IasClassName_Device[]         = "Device";
const CHAR IasAttribName_DeviceName[]    = "DeviceName";
const CHAR IasAttribName_IrLMPSupport[]  = "IrLMPSupport";
const CHAR IasAttribName_TTPLsapSel[]    = "IrDA:TinyTP:LsapSel";
const CHAR IasAttribName_IrLMPLsapSel[]  = "IrDA:IrLMP:LsapSel";
const CHAR IasAttribName_IrLMPLsapSel2[] = "IrDA:IrLMP:LSAPSel"; // jeez

const UCHAR IasClassNameLen_Device        = sizeof(IasClassName_Device)-1;
const UCHAR IasAttribNameLen_DeviceName   = sizeof(IasAttribName_DeviceName)-1;
const UCHAR IasAttribNameLen_IrLMPSupport = sizeof(IasAttribName_IrLMPSupport)-1;
const UCHAR IasAttribNameLen_TTPLsapSel   = sizeof(IasAttribName_TTPLsapSel)-1;
const UCHAR IasAttribNameLen_IrLMPLsapSel = sizeof(IasAttribName_IrLMPLsapSel)-1;

// Globals
LIST_ENTRY      RegisteredLsaps;
LIST_ENTRY      DeviceList;
LIST_ENTRY      IasObjects;
IRDA_EVENT      EvDiscoveryReq;
IRDA_EVENT      EvConnectReq;
IRDA_EVENT      EvConnectResp;
IRDA_EVENT      EvLmConnectReq;
IRDA_EVENT      EvIrlmpCloseLink;
BOOLEAN         DscvReqScheduled;
LIST_ENTRY      IrdaLinkCbList;
NDIS_SPIN_LOCK  SpinLock;

// Prototypes
STATIC UINT CreateLsap(PIRLMP_LINK_CB, IRLMP_LSAP_CB **);
STATIC VOID DeleteLsap(IRLMP_LSAP_CB *);
STATIC VOID CleanupLsap(IRLMP_LSAP_CB *pLsapCb);
STATIC VOID TearDownConnections(PIRLMP_LINK_CB, IRLMP_DISC_REASON);
STATIC VOID IrlmpMoreCreditReq(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC VOID IrlmpDiscoveryReq(IRDA_MSG *pMsg);
STATIC UINT IrlmpLinkControlReq(IRDA_MSG *);
STATIC UINT IrlmpConnectReq(IRDA_MSG *);
STATIC UINT IrlmpConnectResp(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC UINT IrlmpDisconnectReq(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC UINT IrlmpDataReqExclusive(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC UINT IrlmpDataReqMultiplexed(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC VOID FormatAndSendDataReq(IRLMP_LSAP_CB *, IRDA_MSG *, BOOLEAN);
STATIC UINT IrlmpAccessModeReq(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC void SetupTtp(IRLMP_LSAP_CB *);
STATIC VOID SendCntlPdu(IRLMP_LSAP_CB *, int, int, int, int);
STATIC VOID LsapResponseTimerExp(PVOID);
STATIC VOID IrlapDiscoveryConf(PIRLMP_LINK_CB, IRDA_MSG *);
STATIC void UpdateDeviceList(PIRDA_LINK_CB, LIST_ENTRY *);
STATIC VOID IrlapConnectInd(PIRLMP_LINK_CB, IRDA_MSG *pMsg);
STATIC VOID IrlapConnectConf(PIRLMP_LINK_CB, IRDA_MSG *pMsg);
STATIC VOID IrlapDisconnectInd(PIRLMP_LINK_CB, IRDA_MSG *pMsg);
STATIC IRLMP_LSAP_CB *GetLsapInState(PIRLMP_LINK_CB, int, int, BOOLEAN);
STATIC IRLMP_LINK_CB *GetIrlmpCb(PUCHAR);
STATIC VOID DiscDelayTimerFunc(PVOID);
STATIC VOID IrlapDataConf(IRDA_MSG *pMsg);
STATIC VOID IrlapDataInd(PIRLMP_LINK_CB, IRDA_MSG *pMsg);
STATIC VOID LmPduConnectReq(PIRLMP_LINK_CB, IRDA_MSG *, int, int, UCHAR *);
STATIC VOID LmPduConnectConf(PIRLMP_LINK_CB, IRDA_MSG *, int, int, UCHAR *);
STATIC VOID LmPduDisconnectReq(PIRLMP_LINK_CB, IRDA_MSG *, int, int, UCHAR *);
STATIC VOID SendCreditPdu(IRLMP_LSAP_CB *);
STATIC VOID LmPduData(PIRLMP_LINK_CB, IRDA_MSG *, int, int);
STATIC VOID SetupTtpAndStoreConnData(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC VOID LmPduAccessModeReq(PIRLMP_LINK_CB, int, int, UCHAR *, UCHAR *);
STATIC VOID LmPduAccessModeConf(PIRLMP_LINK_CB, int, int, UCHAR *, UCHAR *);
STATIC IRLMP_LSAP_CB *GetLsap(PIRLMP_LINK_CB, int, int);
STATIC VOID UnroutableSendLMDisc(PIRLMP_LINK_CB, int, int);
STATIC VOID ScheduleConnectReq(PIRLMP_LINK_CB);
STATIC void InitiateCloseLink(PVOID Context);
STATIC void InitiateConnectReq(PVOID Context);
STATIC void InitiateDiscoveryReq(PVOID Context);
STATIC void InitiateConnectResp(PVOID Context);
STATIC void InitiateLMConnectReq(PVOID Context);
STATIC UINT IrlmpGetValueByClassReq(IRDA_MSG *);
STATIC IAS_OBJECT *IasGetObject(CHAR *pClassName);
STATIC IasGetValueByClass(const CHAR *, int, const CHAR *, int, void **,
                           int *, UCHAR *);
STATIC VOID IasConnectReq(PIRLMP_LINK_CB, int);
STATIC VOID IasServerDisconnectReq(IRLMP_LSAP_CB *pLsapCb);
STATIC VOID IasClientDisconnectReq(IRLMP_LSAP_CB *pLsapCb, IRLMP_DISC_REASON);
STATIC VOID IasSendQueryResp(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC VOID IasProcessQueryResp(PIRLMP_LINK_CB, IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC VOID SendGetValueByClassReq(IRLMP_LSAP_CB *);
STATIC VOID SendGetValueByClassResp(IRLMP_LSAP_CB *, IRDA_MSG *);
STATIC VOID RegisterLsapProtocol(int Lsap, BOOLEAN UseTTP);
STATIC UINT IasAddAttribute(IAS_SET *pIASSet, PVOID *pAttribHandle);
STATIC VOID IasDelAttribute(PVOID AttribHandle);

STATIC VOID UpdateIasDeviceName(PIRLMP_LINK_CB pIrlmpCb);

/*****************************************************************************
*
*/
VOID
IrlmpInitialize()
{
    InitializeListHead(&RegisteredLsaps);
    InitializeListHead(&DeviceList);
    InitializeListHead(&IasObjects);
    InitializeListHead(&IrdaLinkCbList);

    NdisAllocateSpinLock(&SpinLock);
        
    DscvReqScheduled = FALSE;
    IrdaEventInitialize(&EvDiscoveryReq, InitiateDiscoveryReq);        
    IrdaEventInitialize(&EvConnectReq, InitiateConnectReq);
    IrdaEventInitialize(&EvConnectResp,InitiateConnectResp);
    IrdaEventInitialize(&EvLmConnectReq, InitiateLMConnectReq);
    IrdaEventInitialize(&EvIrlmpCloseLink, InitiateCloseLink);
}    

/*****************************************************************************
*
*/
VOID
IrdaShutdown()
{
    PIRDA_LINK_CB   pIrdaLinkCb, pIrdaLinkCbNext;
#ifndef UNDER_CE
    LARGE_INTEGER   SleepMs;
#endif 
    NTSTATUS        Status;
    UINT            Seconds;


    // This needs to be fixed

#ifndef UNDER_CE
    SleepMs.QuadPart = -(10*1000*1000); // 1 second
#endif 

    NdisAcquireSpinLock(&SpinLock);

    for (pIrdaLinkCb = (PIRDA_LINK_CB) IrdaLinkCbList.Flink;
         (LIST_ENTRY *) pIrdaLinkCb != &IrdaLinkCbList;
         pIrdaLinkCb = pIrdaLinkCbNext)
    {
        pIrdaLinkCbNext = (PIRDA_LINK_CB) pIrdaLinkCb->Linkage.Flink;

        NdisReleaseSpinLock(&SpinLock);

        IrlmpCloseLink(pIrdaLinkCb);

        NdisAcquireSpinLock(&SpinLock);
    }

    NdisReleaseSpinLock(&SpinLock);

    Seconds = 0;
    while (Seconds < 30)
    {
        if (IsListEmpty(&IrdaLinkCbList))
            break;
    #ifdef UNDER_CE
        Sleep(1000);
    #else 
        KeDelayExecutionThread(KernelMode, FALSE, &SleepMs);
    #endif 

        Seconds++;
    }

#ifdef UNDER_CE
    Sleep(1000);
    ASSERT(Seconds < 30);
#else 

#if DBG
    if (Seconds >= 30)
    {
        DbgPrint("Link left open at shutdown!\n");

        for (pIrdaLinkCb = (PIRDA_LINK_CB) IrdaLinkCbList.Flink;
             (LIST_ENTRY *) pIrdaLinkCb != &IrdaLinkCbList;
            pIrdaLinkCb = pIrdaLinkCbNext)
        {
            DbgPrint("pIrdaLinkCb: %X\n", pIrdaLinkCb);
            DbgPrint("   pIrlmpCb: %X\n", pIrdaLinkCb->IrlmpContext);
            DbgPrint("   pIrlapCb: %X\n", pIrdaLinkCb->IrlapContext);
        }
        ASSERT(0);
    }
    else
    {
        DbgPrint("Irda shutdown complete\n");
    }
#endif 

    KeDelayExecutionThread(KernelMode, FALSE, &SleepMs);
#endif 

    NdisFreeSpinLock(&SpinLock);
    NdisDeregisterProtocol(&Status, NdisIrdaHandle);
}
/*****************************************************************************
*
*/
VOID
IrlmpOpenLink(OUT PNTSTATUS       Status,
              IN  PIRDA_LINK_CB   pIrdaLinkCb,  
              IN  UCHAR           *pDeviceName,
              IN  int             DeviceNameLen,
              IN  UCHAR           CharSet)
{
    PIRLMP_LINK_CB   pIrlmpCb;
    UINT             rc;
    IAS_SET          *pIASSet;

    *Status = STATUS_SUCCESS;

    if ((pIrlmpCb = CTEAllocMem(sizeof(IRLMP_LINK_CB))) == NULL)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("Alloc failed\n")));
        *Status = STATUS_INSUFFICIENT_RESOURCES;
        return;
    }

    pIASSet = (IAS_SET *)IrdaAlloc(sizeof(IAS_SET) + 128, 0);
    if (NULL == pIASSet) {
        CTEFreeMem(pIrlmpCb);
        DEBUGMSG(DBG_ERROR, (TEXT("IAS_SET Alloc failed\n")));
        *Status = STATUS_INSUFFICIENT_RESOURCES;
        return;
    }

    pIrdaLinkCb->IrlmpContext = pIrlmpCb;
    
#if DBG
    pIrlmpCb->DiscDelayTimer.pName = "DiscDelay";
#endif
    IrdaTimerInitialize(&pIrlmpCb->DiscDelayTimer,
                        DiscDelayTimerFunc,
                        IRLMP_DISCONNECT_DELAY_TIMEOUT,
                        pIrlmpCb,
                        pIrdaLinkCb);
    
    InitializeListHead(&pIrlmpCb->LsapCbList);

    pIrlmpCb->pIrdaLinkCb       = pIrdaLinkCb;
    pIrlmpCb->ConnReqScheduled  = FALSE;
    pIrlmpCb->LinkState         = LINK_DISCONNECTED;
    pIrlmpCb->pExclLsapCb       = NULL; 
    pIrlmpCb->pIasQuery         = NULL;

    // ConnDevAddrSet is set to true if LINK_IN_DISCOVERY or
    // LINK_DISCONNECTING and an LSAP requests a connection. Subsequent
    // LSAP connection requests check to see if this flag is set. If so
    // the requested device address must match that contained in the
    // IRLMP control block (set by the first connect request)
    pIrlmpCb->ConnDevAddrSet = FALSE;

    // Add device info to IAS        
    RtlCopyMemory(pIASSet->irdaClassName, IasClassName_Device,
                  IasClassNameLen_Device+1);
    RtlCopyMemory(pIASSet->irdaAttribName, IasAttribName_DeviceName,
                  IasAttribNameLen_DeviceName+1);
    pIASSet->irdaAttribType = IAS_ATTRIB_VAL_STRING;

    DeviceNameLen = min(DeviceNameLen, sizeof(pIASSet->irdaAttribute.irdaAttribUsrStr.UsrStr));
    RtlCopyMemory(pIASSet->irdaAttribute.irdaAttribUsrStr.UsrStr,
                  pDeviceName, 
                  DeviceNameLen + 1);
    pIASSet->irdaAttribute.irdaAttribUsrStr.CharSet = CharSet;
    pIASSet->irdaAttribute.irdaAttribUsrStr.Len = DeviceNameLen;        
    rc = IasAddAttribute(pIASSet, &pIrlmpCb->hAttribDeviceName);
    ASSERT(rc == 0);

    RtlCopyMemory(pIASSet->irdaClassName, IasClassName_Device,
                  IasClassNameLen_Device+1);
    RtlCopyMemory(pIASSet->irdaAttribName, IasAttribName_IrLMPSupport, 
                  IasAttribNameLen_IrLMPSupport+1);
    pIASSet->irdaAttribType = IAS_ATTRIB_VAL_BINARY;
    RtlCopyMemory(pIASSet->irdaAttribute.irdaAttribOctetSeq.OctetSeq, 
           IAS_IrLMPSupport, sizeof(IAS_IrLMPSupport));
    pIASSet->irdaAttribute.irdaAttribOctetSeq.Len =  
        sizeof(IAS_IrLMPSupport);
        
    rc = IasAddAttribute(pIASSet, &pIrlmpCb->hAttribIrlmpSupport);
    ASSERT(rc == 0);

    if (*Status != STATUS_SUCCESS)
    {
        CTEFreeMem(pIrlmpCb);
    }
    else
    {
        NdisInterlockedInsertTailList(&IrdaLinkCbList,
                                      &pIrdaLinkCb->Linkage,
                                      &SpinLock);
    }

    IrdaFree(pIASSet);
    
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP initialized, status %x\n"), *Status));
    
    return;
}

/*****************************************************************************
*
*
*
*/
VOID
IrlmpDeleteInstance(PVOID Context)
{
    PIRLMP_LINK_CB  pIrlmpCb = (PIRLMP_LINK_CB) Context;
    PVOID           LinkContext = pIrlmpCb->pIrdaLinkCb;
    IRDA_DEVICE     *pDevice, *pNextDevice;
    
    NdisAcquireSpinLock(&SpinLock);
    
    for (pDevice = (IRDA_DEVICE *) DeviceList.Flink;
         (LIST_ENTRY *) pDevice != &DeviceList;
         pDevice = pNextDevice)
    {
        pNextDevice = (IRDA_DEVICE *) pDevice->Linkage.Flink;
        
        if (LinkContext == pDevice->LinkContext)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -