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

📄 ircomm.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.
//
// ircomm.c - Emulate a com port on top of IRDA winsock
//
#include "windows.h"
#include "memory.h"
#include "pegdser.h"
#include "winsock2.h"
#include "af_irda.h"
#include <devload.h>

#undef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))

DWORD WINAPI AcceptThread(PVOID pThreadParm);
DWORD WINAPI TxThread(PVOID pThreadParm);
DWORD WINAPI RxThread(PVOID pThreadParm);

int     IrCOMMConnect(void);
int     InitializeConnection(SOCKET);
TCHAR   *GetLastErrorText(void);
int     CreateSockets();

#ifdef DEBUG

// Debug zone definitions.
#define ZONE_STATE      DEBUGZONE(0)	// 0x0001
#define ZONE_SOCKET     DEBUGZONE(1)	// 0x0002
#define ZONE_RECV       DEBUGZONE(7)    // 0x0080
#define ZONE_CONN       DEBUGZONE(8)    // 0x0100
#define ZONE_SEND       DEBUGZONE(9)    // 0x0200
#define ZONE_INTERFACE  DEBUGZONE(10)   // 0x0400
#define ZONE_MISC       DEBUGZONE(11)   // 0x0800
#define ZONE_ALLOC      DEBUGZONE(12)   // 0x1000
#define ZONE_FUNCTION   DEBUGZONE(13)   // 0x2000
#define ZONE_WARN       DEBUGZONE(14)   // 0x4000
#define ZONE_ERROR      DEBUGZONE(15)   // 0x8000

DBGPARAM dpCurSettings = 
{
    TEXT("IrComm"), 
    {
        TEXT("State"), TEXT("Socket"),  TEXT("Unused"),  TEXT("Unused"),
        TEXT("Unused"), TEXT("Unused"), TEXT("Unused"),  TEXT("Recv"),
        TEXT("Conn"),  TEXT("Send"),    TEXT("Interface"), TEXT("Misc"),
        TEXT("Alloc"), TEXT("Function"), TEXT("Warning"), TEXT("Error") 
    },
    0xC003
};

TCHAR *StateStr[] = {
    TEXT("IRCOMM_CLOSED"),
    TEXT("IRCOMM_OPENED"),
    TEXT("IRCOMM_DISCOVERY_PENDING"),
    TEXT("IRCOMM_CONNECT_PENDING"),
    TEXT("IRCOMM_CONNECTED")
};
#endif

typedef enum 
{
    IRCOMM_CLOSED,
    IRCOMM_OPENED,
    IRCOMM_DISCOVERY_PENDING,
    IRCOMM_CONNECT_PENDING,
    IRCOMM_CONNECTED
} IRCOMM_CONN_STATES;

typedef struct 
{
    BYTE    PIDataRate_0x10;
    BYTE    PLDataRate_4;
    ULONG   PVDataRateBigEndian;
    BYTE    PIDataFmt_0x11;
    BYTE    PLDataFmt_1;
    BYTE    PVDataFmt;
    BYTE    PIFlowCtl_0x12;
    BYTE    PLFlowCtl_1;
    BYTE    PVFlowCtl;
    BYTE    PIXOnXoff_0x13;
    BYTE    PLXOnXoff_2;
    BYTE    PVXOn_0x11;
    BYTE    PVXOff_0x13;
    BYTE    PIEnqAck_0x14;
    BYTE    PLEnqAck_2;
    BYTE    PVEnq_0x05;
    BYTE    PVAck_0x06;
} IRCOMM_9WIRE_PARMS;

SOCKADDR_IRDA SockAddr = 
{
    AF_IRDA,
    0, 0, 0, 0,
    "IrDA:IrCOMM"
};

#define MAX_OPENS 8
typedef struct _IRCOMM_OPEN {
    DWORD dwEventMask;
    DWORD dwEventData;
    HANDLE hCommEvent;
    DWORD  dwWaitThds;
    DWORD dwRefCnt;
} IRCOMM_OPEN, *PIRCOMM_OPEN;

PIRCOMM_OPEN g_Opens[MAX_OPENS];

HANDLE              hTxEvent;
HANDLE              hRxEvent;

PIRCOMM_OPEN        vAccessOwner;               
DWORD               vEventMask; // OR of wait masks of all opens
CRITICAL_SECTION    IrcommCs;
CRITICAL_SECTION    IrcommCs;

IRCOMM_CONN_STATES  State;

int                 SendMaxPDU;

SOCKET              ListenSock = INVALID_SOCKET;
SOCKET              AcceptSock = INVALID_SOCKET;
SOCKET              ConnectSock = INVALID_SOCKET;
SOCKET              DataSock = INVALID_SOCKET;
BOOL                SocketsCreated = FALSE;
DWORD               g_dwListenInstance = 0;

BYTE                *pMemBase;

#define             IRCOMM_TX_RING_SIZE     4096
BYTE                *TxRing;
BYTE                *pTxRingRead;
BYTE                *pTxRingWrite;
BYTE                *pTxRingMax;

#define             IRCOMM_TX_BUF_SIZE      2048
BYTE                *TxBuf;

#define             IRCOMM_RX_RING_SIZE     4096
BYTE                *RxRing;
BYTE                *pRxRingRead;
BYTE                *pRxRingWrite;
BYTE                *pRxRingMax;

COMMTIMEOUTS        CommTimeouts;

// WaitEvent thread priority
#define 			DEFAULT_THREAD_PRIORITY 148
#define 			REGISTRY_PRIORITY_VALUE TEXT("Priority256")
DWORD				g_dwHighThreadPrio;


BOOL __stdcall
DllEntry (HANDLE  hinstDLL,
          DWORD   Op,
          LPVOID  lpvReserved)
{
    switch (Op)
    {
      case DLL_PROCESS_ATTACH:
        DEBUGREGISTER(hinstDLL);
		DisableThreadLibraryCalls ((HMODULE)hinstDLL);
        break;

      case DLL_PROCESS_DETACH:
        break;
        
      case DLL_THREAD_DETACH:
        break;
        
      case DLL_THREAD_ATTACH:
        break;
        
        default :
        break;
    }
    
    return(TRUE);
}


//
// Allocate and initialize a new IRCOMM_OPEN
//
DWORD
NewOpen(
    DWORD dwAccess
    )
{
    DWORD i;
    PIRCOMM_OPEN pOpen;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:+NewOpen\n")));
    EnterCriticalSection(&IrcommCs);
    for (i = 0; i < MAX_OPENS; i++) {
        if (NULL == g_Opens[i]) {
            pOpen = LocalAlloc(LPTR, sizeof(IRCOMM_OPEN));
            if (NULL == pOpen) {
                i = MAX_OPENS;
                DEBUGMSG(ZONE_WARN, (TEXT("IRCOMM:NewOpen LocalAlloc failed\n")));
                break;
            }
            pOpen->hCommEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            pOpen->dwRefCnt = 1;
            pOpen->dwWaitThds = 0;
            if (NULL == pOpen->hCommEvent) {
                LocalFree(pOpen);
                i = MAX_OPENS;
                DEBUGMSG(ZONE_WARN, (TEXT("IRCOMM:NewOpen CreateEvent failed\n")));
                break;
            }
            g_Opens[i] = pOpen;
            if (dwAccess & (GENERIC_READ|GENERIC_WRITE)) {
                vAccessOwner = pOpen;
            }
            break;
        }
    }
    LeaveCriticalSection(&IrcommCs);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:-NewOpen %d\n"), i));
    return i+1;
}   // NewOpen


BOOL
DerefOpen(
    DWORD dwOpen
    )
{
    PIRCOMM_OPEN pOpen;
    BOOL bDelete = FALSE;
    DWORD dwIndex = dwOpen-1;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:+DerefOpen %d\n"), dwOpen));
    EnterCriticalSection(&IrcommCs);
    pOpen = g_Opens[dwIndex];
    pOpen->dwRefCnt--;
    if (0 == pOpen->dwRefCnt) {
        g_Opens[dwIndex] = NULL;
        if (pOpen == vAccessOwner) {
            vAccessOwner = NULL;
        }
        bDelete = TRUE;
    }

    if (bDelete) {
        DEBUGMSG(ZONE_WARN, (TEXT("IRCOMM:DerefOpen delete %d\n"), dwOpen));
        
        dwIndex = pOpen->dwWaitThds;
        while (dwIndex) {
            SetEvent(pOpen->hCommEvent);
            dwIndex--;
        }

        LeaveCriticalSection(&IrcommCs);

        CloseHandle(pOpen->hCommEvent);
        LocalFree(pOpen);
    } else {
        LeaveCriticalSection(&IrcommCs);
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:-DerefOpen %d\n"), dwOpen));
    return bDelete;
}   // DerefOpen


//
// Verify an open handle and reference it.
//
PIRCOMM_OPEN
IsValidOpen(
    DWORD dwOpen
    )
{
    PIRCOMM_OPEN pRet;
    DWORD dwIndex = dwOpen-1;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:+IsValidOpen %d\n"), dwOpen));

    if (dwIndex >= MAX_OPENS) {
        DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:-IsValidOpen %d too large\n"), dwOpen));
        return NULL;
    }

    EnterCriticalSection(&IrcommCs);
    if (pRet = g_Opens[dwIndex]) {
        g_Opens[dwIndex]->dwRefCnt++;
    }
    LeaveCriticalSection(&IrcommCs);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:-IsValidOpen 0x%x\n"), pRet));
    return pRet;
}   // IsValidOpen

//
// Wake any threads waiting on a new event
//
void
NewCommEvent(
    DWORD dwEventData
    )
{
    DWORD i, j;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:+NewCommEvent 0x%x\n"), dwEventData));
    EnterCriticalSection(&IrcommCs);
    if (dwEventData & vEventMask) { // Is anyone interested in this EV_*
        for (i = 0; i < MAX_OPENS; i++) {
            if (g_Opens[i]) {
                if (g_Opens[i]->dwEventMask & dwEventData) {
                    g_Opens[i]->dwEventData |= g_Opens[i]->dwEventMask & dwEventData;
                    j = g_Opens[i]->dwWaitThds;
                    while (j) {
                        SetEvent(g_Opens[i]->hCommEvent);
                        j--;
                    }
                }
            }
        }
    }
    LeaveCriticalSection(&IrcommCs);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("IRCOMM:-NewCommEvent\n")));
}   // NewCommEvent


void
ComputeEventMaskOR(void)
{
    int i;

    EnterCriticalSection(&IrcommCs);
    //
    // Recompute the OR of all wait masks
    //
    vEventMask = 0;
    for (i = 0; i < MAX_OPENS; i++) {
        if (g_Opens[i]) {
            vEventMask |= g_Opens[i]->dwEventMask;
        }
    }
    LeaveCriticalSection(&IrcommCs);
}

__inline
void
NewState(IRCOMM_CONN_STATES NewState)
{
    DEBUGMSG(ZONE_STATE, (TEXT("IRCOMM:NewState %s\r\n"), StateStr[NewState]));

    State = NewState;
}


//
// If the app is monitoring incoming calls (like PPP server) then don't transition to CLOSED.
// The next WaitCommEvent or ReadFile will cause IRCOMM to create a new set of sockets.
//
void
Shutdown(
    BOOL bClose
    )
{
    EnterCriticalSection(&IrcommCs);

    if (State != IRCOMM_CLOSED)
    {
        NewState(bClose ? IRCOMM_CLOSED : IRCOMM_OPENED);

        NewCommEvent(EV_RLSD);

        if (SocketsCreated) {
            // Indicate to any existing accept threads that their ListenSock is no longer valid.
            ++g_dwListenInstance;
	
            DEBUGMSG (ZONE_WARN, (TEXT("IRCOMM:Shutdown: Closing socket %d (ListenSock)\r\n"), ListenSock));
            closesocket(ListenSock);
            DEBUGMSG (ZONE_WARN, (TEXT("IRCOMM:Shutdown: Closing socket %d (ConnectSock)\r\n"), ConnectSock));
            closesocket(ConnectSock);            
            DEBUGMSG (ZONE_WARN, (TEXT("IRCOMM:Shutdown: Closing socket %d (DataSock)\r\n"), DataSock));
            closesocket(DataSock);

		    ListenSock = INVALID_SOCKET;
            ConnectSock = INVALID_SOCKET;
            DataSock = INVALID_SOCKET;            
        }

⌨️ 快捷键说明

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