📄 l2cap.cxx
字号:
//
// 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.
//
//------------------------------------------------------------------------------
//
// Bluetooth L2CAP Layer
//
//
// Module Name:
//
// l2cap.cxx
//
// Abstract:
//
// This file implements Bluetooth L2CAP Layer
//
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <svsutil.hxx>
#if ! defined (UNDER_CE)
#include <stddef.h>
#endif
#include <bt_debug.h>
#include <bt_os.h>
#include <bt_buffer.h>
#include <bt_hcip.h>
#include <bt_ddi.h>
#include <service.h>
#include <winsock2.h>
#include <bt_api.h>
#define L2CAP_TO 5000
#define L2CAP_LINK_TO 1000
#define L2CAP_SCALE 10
#define L2CAP_FIRST_CID 0x0040
#define L2CAP_FIRST_PSM 0x1001
#define L2CAP_LAST_PSM 0x1001
#define L2CAP_RTX 60
#define L2CAP_ERTX 300
#define L2CAP_PHYSIDLE 10
#define L2CAP_CONNIDLE 10
#define L2CAP_CONFIGTO 120
#define L2CAP_RECONNECT 3
#define L2CAP_MAXBAD 3
#define L2CAP_COMMAND_COMMAND_REJECT 0x01
#define L2CAP_COMMAND_CONNECTION_REQUEST 0x02
#define L2CAP_COMMAND_CONNECTION_RESPONSE 0x03
#define L2CAP_COMMAND_CONFIG_REQUEST 0x04
#define L2CAP_COMMAND_CONFIG_RESPONSE 0x05
#define L2CAP_COMMAND_DISCONNECT_REQUEST 0x06
#define L2CAP_COMMAND_DISCONNECT_RESPONSE 0x07
#define L2CAP_COMMAND_ECHO_REQUEST 0x08
#define L2CAP_COMMAND_ECHO_RESPONSE 0x09
#define L2CAP_COMMAND_INFO_REQUEST 0x0a
#define L2CAP_COMMAND_INFO_RESPONSE 0x0b
#define L2CAP_V_MAJ 1
#define L2CAP_V_MIN 1
enum CONNECTION_STAGE {
STARTING_PHYS, // Waiting physical link
STARTING, // Waiting response
STARTING_REQUEST,
CONFIG,
CONFIG_LOCAL_DONE,
CONFIG_REMOTE_DONE,
UP,
DISCONNECTED
};
enum CALL_OP {
CALL_HCI_READSCAN,
CALL_HCI_WRITESCAN,
CALL_PHYS_CONNECT,
CALL_PHYS_ACCEPT,
CALL_PHYS_DISCONNECT,
CALL_PHYS_DROP_IDLE,
CALL_PHYS_PING,
CALL_LOG_CONNECT_REQ,
CALL_LOG_CONNECT_RESP,
CALL_LOG_CONFIG_REQ,
CALL_LOG_CONFIG_RESP,
CALL_LOG_DISCONNECT_REQ,
CALL_USERDATA,
};
enum CALL_CONTEXT_TYPE {
CALL_CTX_UNINITIALIZED = 0,
CALL_CTX_EVENT,
CALL_CTX_CALLBACK,
CALL_CTX_CALLOWNER,
CALL_CTX_INTERNAL
};
enum L2CAP_STAGE {
JustCreated = 0,
Initializing,
Connected,
Disconnected,
ShuttingDown,
Error
};
class PhysLink;
class LogLink;
class CallContext;
class L2CAP_CONTEXT;
class L2CAP;
class PSMContext {
public:
PSMContext *pNext;
unsigned short usPSM;
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
class L2CAP_CONTEXT : public SVSAllocClass, public SVSRefObj {
public:
L2CAP_CONTEXT *pNext;
L2CAP_EVENT_INDICATION ei;
L2CAP_CALLBACKS c;
void *pUserContext;
PSMContext *pReservedPorts;
int fDefaultServer;
unsigned short usPacketType;
L2CAP_CONTEXT (void) {
pNext = NULL;
memset (&ei, 0, sizeof(ei));
memset (&c, 0, sizeof(c));
pUserContext = NULL;
pReservedPorts = NULL;
fDefaultServer = FALSE;
usPacketType = 0;
}
};
class PhysLink {
public:
PhysLink *pNext;
DWORD dwTimeOutCookie;
BD_ADDR b;
unsigned short h;
unsigned char mode;
CONNECTION_STAGE eStage;
LogLink *pLogLinks;
unsigned int iConnectionAttempts;
unsigned int iTransmissionProblems;
unsigned int iPingsSent;
unsigned short usPacketType;
int iLockCnt;
PhysLink (void) {
memset (this, 0, sizeof(PhysLink));
eStage = STARTING;
h = BT_HCI_INVALID_HANDLE;
}
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
class LogLink {
public:
LogLink *pNext;
DWORD dwTimeOutCookie;
PhysLink *pPhysLink;
unsigned short psm;
unsigned short cid;
unsigned short cid_remote;
CONNECTION_STAGE eStage;
L2CAP_CONTEXT *pOwner;
LogLink (PhysLink *pPhys, L2CAP_CONTEXT *a_pOwner) {
pNext = pPhys->pLogLinks;
pPhys->pLogLinks = this;
dwTimeOutCookie = 0;
pPhysLink = pPhys;
psm = 0;
cid = INVALID_CID;
cid_remote = INVALID_CID;
eStage = pPhys->eStage == UP ? STARTING : STARTING_PHYS;
pOwner = a_pOwner;
}
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
typedef int (*ContextCallback) (CallContext *pContext, int iErr);
class CallContext {
public:
CallContext *pNext;
DWORD dwTimeOutCookie;
CALL_OP eWhat;
union {
void *pLink;
LogLink *pLogLink;
PhysLink *pPhysLink;
} u;
unsigned int id : 8;
unsigned int fForeignId : 1;
unsigned int fComplete : 1;
unsigned int fKeepOnAbort : 1;
unsigned int fRespPending : 1;
unsigned int iResult;
L2CAP_CONTEXT *pOwner;
void *pContext;
CALL_CONTEXT_TYPE eType;
union {
HANDLE hEvent;
ContextCallback pCallback;
};
int cData;
void *pData;
union {
unsigned char ucresult[8];
unsigned short usresult[4];
unsigned int uiresult[2];
} r;
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
class L2CAP : public SVSAllocClass, public SVSSynch, public SVSRefObj {
public:
PhysLink *pPhysLinks;
L2CAP_CONTEXT *pContexts;
CallContext *pCalls;
L2CAP_STAGE eStage;
FixedMemDescr *pfmdPhysLinks;
FixedMemDescr *pfmdLogLinks;
FixedMemDescr *pfmdCallContexts;
FixedMemDescr *pfmdPSM;
HCI_INTERFACE hci_if;
HANDLE hHCI;
int cHCIHeader;
int cHCITrailer;
int iEchoes;
unsigned short usCurrentPSM;
unsigned short usCurrentCID;
unsigned char ucCurrentID;
// Configurable parameters
unsigned char bRole;
unsigned short usLinkPolicy;
unsigned short usPacketType;
unsigned int RTX;
unsigned int ERTX;
DWORD dwPhysIdle;
DWORD dwConnectIdle;
DWORD dwConfigTO;
unsigned int fPicoCapable : 1;
unsigned int fScanModeControl : 1;
void ReInit (void) {
pPhysLinks = NULL;
pContexts = NULL;
pCalls = NULL;
eStage = JustCreated;
pfmdPhysLinks = NULL;
pfmdLogLinks = NULL;
pfmdCallContexts = NULL;
pfmdPSM = NULL;
memset (&hci_if, 0, sizeof(hci_if));
hHCI = NULL;
cHCIHeader = 0;
cHCITrailer = 0;
iEchoes = 0;
usCurrentPSM = L2CAP_FIRST_PSM;
usCurrentCID = L2CAP_FIRST_CID;
ucCurrentID = 0;
bRole = 0;
usLinkPolicy = 0xffff;
usPacketType = 0;
RTX = 0;
ERTX = 0;
dwPhysIdle = 0;
dwConnectIdle = 0;
dwConfigTO = 0;
fPicoCapable = FALSE;
fScanModeControl = TRUE;
}
L2CAP (void) {
ReInit ();
}
int IsStackRunning (void) {
return (eStage == Connected) || (eStage == Disconnected);
}
};
struct CONFIG_OPT {
unsigned char type;
unsigned char length;
union {
unsigned short MTU;
unsigned short FlushTimeout;
unsigned char QoS[22];
} u;
};
struct SignallingPacket {
struct {
unsigned char code;
unsigned char id;
unsigned short length;
} h;
union {
struct {
unsigned short reason;
unsigned char ucOptionalData[4];
} COMMAND_REJECT;
struct {
unsigned short psm;
unsigned short source_cid;
} CONNECTION_REQUEST;
struct {
unsigned short dest_cid;
unsigned short source_cid;
unsigned short result;
unsigned short status;
} CONNECTION_RESPONSE;
struct {
unsigned short dest_cid;
unsigned short flags;
unsigned char optbuf[sizeof(CONFIG_OPT) * 3];
} CONFIG_REQUEST;
struct {
unsigned short source_cid;
unsigned short flags;
unsigned short result;
unsigned char optbuf[sizeof(CONFIG_OPT) * 3];
} CONFIG_RESPONSE;
struct {
unsigned short dest_cid;
unsigned short source_cid;
} DISCONNECT_REQUEST, DISCONNECT_RESPONSE;
struct {
unsigned char ucData[256];
} ECHO_REQUEST, ECHO_RESPONSE;
struct {
unsigned short info_type;
} INFO_REQUEST;
struct {
unsigned short info_type;
unsigned short result;
unsigned char ucData[1];
} INFO_RESPONSE;
} u;
};
struct Signal {
unsigned short length;
unsigned short cid;
SignallingPacket packet;
};
static inline int SIGNAL_LENGTH(Signal &s) {
return (offsetof (Signal, packet) + s.length);
}
static L2CAP *gpL2CAP = NULL;
static CallContext *AllocCallContext (CALL_CONTEXT_TYPE eType, CALL_OP eOp, void *pLink, L2CAP_CONTEXT *pOwner, void *pCallContext);
static void ResetCallContext (CallContext *pContext);
static void DeleteCallContext (CallContext *pContext);
static int CancelCall (CallContext *pCall, int iError);
static void DisconnectLogicalLink (LogLink *pLink, int iErr, int fSendDisconnect);
static int DisconnectPhysicalLink (PhysLink *pPhysLink, int fReconnect, int iErr, CallContext *pCallContext);
#if defined (DEBUG) || defined (_DEBUG)
static void DumpBuff (unsigned int cMask, BD_BUFFER *pBuff) {
DumpBuff (cMask, pBuff->pBuffer + pBuff->cStart, BufferTotal (pBuff));
}
#else
static void DumpBuff (unsigned int cMask, BD_BUFFER *pB) {}
#endif
static void AbortCall (CallContext *pCall, int iErr);
static PhysLink *FindPhys (unsigned short h) {
PhysLink *pP = gpL2CAP->pPhysLinks;
while (pP && (pP->h != h))
pP = pP->pNext;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -