📄 sdpbase.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 SDP Layer
//
//
// Module Name:
//
// sdpbase.cxx
//
// Abstract:
//
// This file implements SDP layer.
//
//
//------------------------------------------------------------------------------
#include "common.h"
#include <svsutil.hxx>
#include <bt_debug.h>
#define CALL_SDP_SERVICE_SEARCH 0x0001
#define CALL_SDP_ATTRIBUTE_SEARCH 0x0002
#define CALL_SDP_SERVICE_ATTRIBUTE_SEARCH 0x0004
#define CALL_SDP_ACCEPT 0x0008
#define CALL_SDP_CONNECT 0x0010
#define CALL_SDP_DISCONNECT 0x0020
#define CALL_SDP_SERVER_WORKER 0x0040
#define CALL_SDP_SEARCH (CALL_SDP_SERVICE_SEARCH | CALL_SDP_ATTRIBUTE_SEARCH | CALL_SDP_SERVICE_ATTRIBUTE_SEARCH)
#define CALL_SDP_ACCEPT_CONNECT (CALL_SDP_ACCEPT | CALL_SDP_CONNECT)
#define CALL_SDP_ACCEPT_SEARCH (CALL_SDP_SEARCH | CALL_SDP_ACCEPT)
#define CALL_SDP_SEARCH_WORKER (CALL_SDP_SEARCH | CALL_SDP_SERVER_WORKER)
#define NONE 0x00
#define CONNECTED 0x01
#define CONFIG_REQ_DONE 0x02
#define CONFIG_IND_DONE 0x04
#define UP 0x07
#define LINK_ERROR 0x80
#define DEFAULT_IN_MTU_SIZE 0x1000
#define MAX_MTU_SIZE 0xFFFF
#define SDP_SCALE 10
enum SDP_STAGE {
JustCreated = 0,
Initializing,
Connected,
Disconnected,
ShuttingDown,
Error
};
#if 0
// Currently no registry settings are available for SDP.
#define SDP_DEFAULT_LINK_TIMEOUT_MS 10000
static const WCHAR g_SdpBaseRegKey[] = L"software\\Microsoft\\bluetooth\\l2cap";
static const WCHAR g_SdpLinkIdle[] = L"SdpLinkIdle";
#endif
struct SDP_CONTEXT : public SVSAllocClass, public SVSRefObj {
SDP_CONTEXT *pNext;
SDP_CALLBACKS c;
SDP_EVENT_INDICATION ei;
void *pUserContext;
SDP_CONTEXT(void) {
memset(&ei, 0, sizeof(ei));
memset(&c, 0, sizeof(c));
pNext = NULL;
}
};
struct Call;
struct CallQueue {
struct CallQueue *pNext;
Call *pCall;
};
struct Link : public SVSAllocClass, public SVSRefObj {
Link *pNext;
BD_ADDR b;
unsigned short psm;
unsigned short cid;
unsigned int fStage;
unsigned int fIncoming : 1;
unsigned int fCallCanceled : 1;
unsigned short inMTU;
unsigned short outMTU;
CallQueue *pCallQueue;
};
struct Call : public SVSAllocClass {
Call *pNext;
Link *pLink;
unsigned int fWhat : 8;
SDP_CONTEXT *pOwner;
void *pCallContext;
SdpConnection *pSdpConnection;
};
static int sdp_ConfigInd(void *pUserContext, unsigned char id, unsigned short cid, unsigned short usOutMTU, unsigned short usInFlushTO, struct btFLOWSPEC *pInFlow, int cOptNum, struct btCONFIGEXTENSION **ppExtendedOptions);
static int sdp_ConnectInd(void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm);
static int sdp_DataUpInd(void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer);
static int sdp_DisconnectInd(void *pUserContext, unsigned short cid, int iErr);
static int sdp_lStackEvent(void *pUserContext, int iEvent, void *pEventContext);
static int sdp_lCallAborted(void *pCallContext, int iError);
static int sdp_ConfigReq_Out(void *pCallContext, unsigned short usResult, unsigned short usInMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **ppExtendedOptions);
static int sdp_ConfigResponse_Out(void *pCallContext, unsigned short result);
static int sdp_ConnectReq_Out(void *pCallContext, unsigned short cid, unsigned short result, unsigned short status);
static int sdp_ConnectResponse_Out(void *pCallContext, unsigned short result);
static int sdp_DataDown_Out(void *pCallContext, unsigned short result);
static int sdp_Disconnect_Out(void *pCallContext, unsigned short result);
static int sdp_InquiryComplete(void *pUserContext, void *pCallContext, unsigned char status, unsigned char num_responses);
static int sdp_InquiryResult(void *pUserContext, void *pCallContext, BD_ADDR *pba, unsigned char page_scan_repetition_mode_list, unsigned char page_scan_period_mode, unsigned char page_scan_mode, unsigned int class_of_device, unsigned short clock_offset);
static int sdp_RemoteNameDone(void *pUserContext, void *pCallContext, unsigned char status, BD_ADDR *pba, unsigned char utf_name[248]);
static int sdp_hStackEvent(void *pUserContext, int iEvent, void *pEventContext);
static int sdp_hCallAborted(void *pCallContext, int iError);
static int sdp_LocalNameDone(void *pCallContext, unsigned char status);
static int sdp_Inquiry_Out(void *pCallContext, unsigned char status);
static int sdp_BDADDR_Out(void *pCallContext, unsigned char status, BD_ADDR *pba);
static int sdp_RemoteName_Out(void *pCallContext, unsigned char status);
static int sdp_WriteScan_Out(void *pCallContext, unsigned char status);
static int SdpDisconnect(Link *pLink, Call *pCall);
static void DeleteCall (Call *pCall);
static int MapStatusToErrorCode(int status);
class SDP : public SVSSynch, public SVSRefObj {
public:
Link *pLinks;
Call *pCalls;
SDP_CONTEXT *pContexts;
HANDLE hL2CAP;
L2CAP_INTERFACE l2cap_if;
FixedMemDescr *pfmdLinks;
FixedMemDescr *pfmdCalls;
FixedMemDescr *pfmdSdpConnections;
FixedMemDescr *pfmdCallQueue;
FixedMemDescr *pfmdBuffers;
// DWORD dwSdpIdle;
SDP_STAGE eStage;
BD_ADDR b;
int cDataHeaders;
int cDataTrailers;
void ReInit(void) {
pLinks = NULL;
pCalls = NULL;
pContexts = NULL;
eStage = JustCreated;
hL2CAP = NULL;
memset(&l2cap_if, 0, sizeof(l2cap_if));
pfmdLinks = NULL;
pfmdCalls = NULL;
pfmdSdpConnections = NULL;
pfmdCallQueue = NULL;
pfmdBuffers = NULL;
memset (&b, 0, sizeof(b));
cDataHeaders = cDataTrailers = 0;
}
SDP(void) {
ReInit();
}
int IsStackRunning (void) {
return (eStage == Connected) || (eStage == Disconnected);
}
};
SDP *gpSDP = NULL;
SdpDatabase *pSdpDB = NULL;
unsigned char *gpSdpReadBuffer = NULL;
//******************************************************************
// Link/call/notification helper functions.
//******************************************************************
static SDP_CONTEXT * VerifyContext(SDP_CONTEXT *pContext) {
SVSUTIL_ASSERT(gpSDP->IsLocked());
SDP_CONTEXT *pTrav = gpSDP->pContexts;
while (pTrav &&(pTrav != pContext))
pTrav = pTrav->pNext;
return pTrav;
}
static SDP *CreateNewSDP(void) {
return new SDP;
}
static SdpDatabase *CreateNewSdpDatabase(void) {
return new SdpDatabase;
}
static Call *VerifyCall(Call *pCall, unsigned char fWhat=0) {
Call *p = gpSDP->pCalls;
while (p && (p != pCall))
p = p->pNext;
// Make sure call type is appropriate for given context.
if (p && fWhat && ! (p->fWhat & fWhat)) {
SVSUTIL_ASSERT(0);
return NULL;
}
return p;
}
static Link *VerifyLink(Link *pLink) {
Link *p = gpSDP->pLinks;
while (p && (p != pLink))
p = p->pNext;
return p;
}
static Call *AllocCall(int fWhat, Link *pLink, SDP_CONTEXT *pOwner, void *pCallContext) {
Call *pCall = (Call *)svsutil_GetFixed(gpSDP->pfmdCalls);
if (!pCall)
return NULL;
memset(pCall, 0, sizeof(*pCall));
pCall->pNext = gpSDP->pCalls;
gpSDP->pCalls = pCall;
pCall->pLink = pLink;
pCall->fWhat = fWhat;
pCall->pOwner = pOwner;
pCall->pCallContext = pCallContext;
return pCall;
}
static Link* AllocLink(void) {
Link *pLink = (Link *)svsutil_GetFixed(gpSDP->pfmdLinks);
if (!pLink)
return NULL;
memset(pLink, 0, sizeof(*pLink));
pLink->AddRef();
pLink->psm = PSM_SDP;
return pLink;
}
static SdpConnection* AllocSdpConnection(Call *pCall) {
SdpConnection *pSdpConn = (SdpConnection*) svsutil_GetFixed(gpSDP->pfmdSdpConnections);
if (!pSdpConn)
return NULL;
memset(pSdpConn ,0,sizeof(*pSdpConn));
pSdpConn->pCallContext = (void *) pCall;
if (pCall) {
pCall->pSdpConnection = pSdpConn;
pCall->pSdpConnection->outMtu = pCall->pLink->outMTU;
pCall->pSdpConnection->inMtu = pCall->pLink->inMTU;
}
return pSdpConn;
}
static CallQueue *AddItemToCallQueue(Link *pLink, Call *pCall) {
CallQueue *pNew = (CallQueue *) svsutil_GetFixed(gpSDP->pfmdCallQueue);
if (!pNew)
return NULL;
pNew->pNext = NULL;
pNew->pCall = pCall;
if (!pLink->pCallQueue)
pLink->pCallQueue = pNew;
else {
CallQueue *pTrav = pLink->pCallQueue;
while (pTrav->pNext)
pTrav = pTrav->pNext;
pTrav->pNext = pNew;
}
return pNew;
}
// need a connection struct for local requests, alloc once when first needed.
static SdpConnection *gpSpdConnectionLocal = NULL;
static SdpConnection* GetLocalSDPConn() {
if (gpSpdConnectionLocal) {
memset((void*)gpSpdConnectionLocal,0,sizeof(*gpSpdConnectionLocal));
return gpSpdConnectionLocal;
}
gpSpdConnectionLocal = AllocSdpConnection(NULL);
return gpSpdConnectionLocal;
}
static void RemoveCallFromSendQueue(Link *pLink, Call *pCall) {
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"RemoveCallFromSendQueue (0x%08x)\r\n",pLink));
SVSUTIL_ASSERT(gpSDP->IsLocked());
SVSUTIL_ASSERT(VerifyLink(pLink));
CallQueue *pTrav = pLink->pCallQueue;
CallQueue *pFollow = NULL;
while (pTrav && (pTrav->pCall != pCall)) {
pFollow = pTrav;
pTrav = pTrav->pNext;
}
if (!pTrav)
return;
if (pFollow)
pFollow->pNext = pTrav->pNext;
else {
SVSUTIL_ASSERT(pLink->pCallQueue->pCall == pCall);
pLink->pCallQueue = pTrav->pNext;
}
svsutil_FreeFixed(pTrav, gpSDP->pfmdCallQueue);
}
void NotifyConnect(SDP_CONTEXT *pOwner, void *pContext, unsigned long status, unsigned short cid) {
SVSUTIL_ASSERT (VerifyContext(pOwner));
SDP_Connect_Out pCallback = pOwner->c.sdp_Connect_Out;
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"About to enter sdp_Connect_Out, pContext=0x%08x,status=0x%08x, cid=0x%04x\r\n",pContext,status,cid));
pOwner->AddRef();
gpSDP->Unlock();
__try {
pCallback(pContext,status,cid);
}
__except (1) {
IFDBG(DebugOut(DEBUG_ERROR,L"sdp_Connect_Out excepted, exception code = 0x%08x\r\n",GetExceptionCode()));
}
gpSDP->Lock();
pOwner->DelRef();
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Finished with sdp_Connect_Out\r\n"));
}
void NotifyDisconnect(SDP_CONTEXT *pOwner, void *pContext, unsigned long status) {
SVSUTIL_ASSERT (VerifyContext(pOwner));
SDP_Disonnect_Out pCallback = pOwner->c.sdp_Disconnect_Out;
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"About to enter sdp_Disconnect_Out, pContext=0x%08x, status=0x%08x\r\n",pContext,status));
pOwner->AddRef();
gpSDP->Unlock();
__try {
pCallback(pContext,status);
}
__except (1) {
IFDBG(DebugOut(DEBUG_ERROR,L"sdp_Disconnect_Out excepted, exception code = 0x%08x\r\n",GetExceptionCode()));
}
gpSDP->Lock();
pOwner->DelRef();
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Finished with sdp_Disconnect_Out\r\n"));
}
void NotifyServiceSearch(SDP_CONTEXT *pOwner, void *pContext, unsigned long status, unsigned short cReturnedHandles, unsigned char *pClientBuf) {
SVSUTIL_ASSERT (VerifyContext(pOwner));
SDP_ServiceSearch_Out pCallback = pOwner->c.sdp_ServiceSearch_Out;
unsigned long *pHandles = NULL;
if (status == ERROR_SUCCESS)
pHandles = (unsigned long *) pClientBuf;
pOwner->AddRef();
gpSDP->Unlock();
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"About to enter sdp_ServiceSearch_Out, pContext=0x%08x\r\n",pContext));
__try {
pCallback(pContext,status,cReturnedHandles,pHandles);
}
__except (1) {
IFDBG(DebugOut(DEBUG_ERROR,L"sdp_ServiceSearch_Out excepted, exception code = 0x%08x\r\n",GetExceptionCode()));
}
gpSDP->Lock();
pOwner->DelRef();
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Finished with sdp_ServiceSearch_Out\r\n"));
}
void NotifyAttributeSearch(SDP_CONTEXT *pOwner, void *pContext, unsigned long status, unsigned char *pClientBuf, unsigned long ulClientBuf) {
SVSUTIL_ASSERT (VerifyContext(pOwner));
SDP_AttributeSearch_Out pCallback = pOwner->c.sdp_AttributeSearch_Out;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -