📄 ircomm.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
// 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 + -