📄 l2capdev.cxx
字号:
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConfigReq_In pCallback = gpState->l2cap_if.l2ca_ConfigReq_In;
gpState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (hL2CAP, pCallContext, cid, mtu, 0xffff, NULL, 0, NULL);
} __except (1) {
}
if (iRes != ERROR_SUCCESS)
l2capdev_lCallAborted (pCallContext, iRes);
return ERROR_SUCCESS;
}
static int l2capdev_DataDown_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: Data down call 0x%08x result %d\n", pCallContext, result));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)pCallContext);
if ((! pCall) || pCall->fComplete) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_DATA_WRITE);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
SVSUTIL_ASSERT (! pCall->pBuffer);
SVSUTIL_ASSERT (! pCall->fAutoClean);
pCall->iResult = ERROR_SUCCESS;
pCall->fComplete = TRUE;
SetEvent (pCall->hEvent);
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int l2capdev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: l2capdev_Ping_Out call 0x%08x result %d\n", pCallContext));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)pCallContext);
if ((! pCall) || pCall->fComplete) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_PING);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (! pCall->pBuffer);
SVSUTIL_ASSERT (! pCall->fAutoClean);
pCall->iResult = ERROR_SUCCESS;
pCall->fComplete = TRUE;
BD_BUFFER *pBuffer = L2CAP_BufferAlloc (size);
if (pBuffer)
memcpy (pBuffer->pBuffer, pOutBuffer, size);
pCall->pBuffer = pBuffer;
SetEvent (pCall->hEvent);
gpState->Unlock ();
return ERROR_SUCCESS;
}
// These are just stubs - they do nothing
static int l2capdev_ConfigResponse_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: ConfigResponse out call 0x%08x, result %d\n", pCallContext, result));
return ERROR_SUCCESS;
}
static int l2capdev_ConnectResponse_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: ConnectResponse out call 0x%08x, result %d\n", pCallContext, result));
return ERROR_SUCCESS;
}
static int l2capdev_Disconnect_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Shell: disconnect out call 0x%08x, result %d\n", pCallContext, result));
return ERROR_SUCCESS;
}
//
// Init stuff
//
int l2capdev_CreateDriverInstance (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+l2capdev_CreateDriverInstance\n"));
if (gpState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CreateDriverInstance : ERROR_ALREADY_INITIALIZED\n"));
return ERROR_ALREADY_INITIALIZED;
}
gpState = CreateNewState ();
if ((! gpState) || (! gpState->fIsRunning)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CreateDriverInstance : ERROR_OUTOFMEMORY\n"));
if (gpState)
delete gpState;
gpState = NULL;
return ERROR_OUTOFMEMORY;
}
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CreateDriverInstance : ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
int l2capdev_CloseDriverInstance (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+l2capdev_CloseDriverInstance\n"));
if (! gpState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->Lock ();
if (! gpState->fIsRunning) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->fIsRunning = FALSE;
while (gpState->GetRefCount () > 1) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Waiting for ref count in l2capdev_CloseDriverInstance\n"));
gpState->Unlock ();
Sleep (200);
gpState->Lock ();
}
while (gpState->pCalls) {
SetEvent (gpState->pCalls->hEvent);
gpState->pCalls->iResult = ERROR_CANCELLED;
gpState->pCalls = gpState->pCalls->pNext;
}
while (gpState->pLinks) {
unsigned short cid = gpState->pLinks->cid;
gpState->Unlock ();
gpState->l2cap_if.l2ca_Disconnect_In (gpState->hL2CAP, NULL, cid);
gpState->Lock ();
gpState->pLinks = gpState->pLinks->pNext;
}
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-l2capdev_CloseDriverInstance : ERROR_SUCCESS\n"));
gpState->Unlock ();
delete gpState;
gpState = NULL;
return ERROR_SUCCESS;
}
//
// Main API section
//
int L2CAPConnect
(
BT_ADDR *pbt,
unsigned short usPSM,
unsigned short usInMTU,
unsigned short *pusCID,
unsigned short *pusOutMTU
) {
BD_ADDR *pba = (BD_ADDR *)pbt;
if (usPSM == 0)
return ERROR_INVALID_PARAMETER;
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
memset (pLink, 0, sizeof (*pLink));
pLink->cid = 0;
pLink->b = *pba;
pLink->fStage = NONE;
pLink->hProcOwner = GetOwnerProcess ();
pLink->inMTU = usInMTU;
pLink->fIncoming = FALSE;
pLink->psm = usPSM;
pLink->pNext = gpState->pLinks;
gpState->pLinks = pLink;
SCall *pCall = AllocCall (CALL_L2CAP_LINK_SETUP, pLink, GetOwnerProcess());
if (! pCall) {
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
HANDLE hEvent = pCall->hEvent;
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConnectReq_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectReq_In;
L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
int iRes = ERROR_INTERNAL_ERROR;
gpState->Unlock ();
__try {
iRes = pCallbackConnect (hL2CAP, pCall, usPSM, pba);
} __except (1) {
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (hEvent, INFINITE);
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (gpState->fIsRunning) {
pCall = VerifyCall (pCall);
pLink = VerifyLink (pLink);
} else {
pCall = NULL;
pLink = NULL;
iRes = ERROR_SERVICE_NOT_ACTIVE;
}
if (iRes == ERROR_SUCCESS) {
if (pCall && pCall->fComplete)
iRes = pCall->iResult;
else
iRes = ERROR_TIMEOUT;
}
if (pCall)
DeleteCall (pCall);
else
iRes = ERROR_INTERNAL_ERROR;
if ((! pLink) || (pLink->fStage & LINK_ERROR) || (iRes != ERROR_SUCCESS) || (pLink->fStage != UP)) {
unsigned short cid_disconnect = 0;
if (pLink) {
if ((iRes == ERROR_SUCCESS) && (pLink->fStage != UP))
iRes = ERROR_INTERNAL_ERROR;
cid_disconnect = pLink->cid;
} else
iRes = ERROR_INTERNAL_ERROR;
gpState->Unlock ();
if (cid_disconnect)
L2CAPCloseCID (cid_disconnect);
return iRes;
}
*pusCID = pLink->cid;
*pusOutMTU = pLink->outMTU;
gpState->Unlock ();
return ERROR_SUCCESS;
}
int L2CAPListen
(
unsigned short usPSM,
unsigned short usInMTU // =>
) {
if (usPSM == 0)
return ERROR_INVALID_PARAMETER;
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
HANDLE h = gpState->hL2CAP;
BT_LAYER_IO_CONTROL pCallback = gpState->l2cap_if.l2ca_ioctl;
int iRes = ERROR_INTERNAL_ERROR;
gpState->AddRef ();
gpState->Unlock ();
__try {
int iRet = 0;
unsigned short usPSMin = usPSM;
iRes = pCallback (h, BTH_STACK_IOCTL_RESERVE_PORT, sizeof(usPSMin), (char *)&usPSMin, sizeof (usPSM), (char *)&usPSM, &iRet);
} __except (1) {
}
gpState->Lock ();
gpState->DelRef ();
if (iRes != ERROR_SUCCESS) {
gpState->Unlock ();
return iRes;
}
Port *p = gpState->pPorts;
while (p && (p->psm != usPSM))
p = p->pNext;
if (p) {
gpState->Unlock ();
return ERROR_ADDRESS_ALREADY_ASSOCIATED;
}
p = (Port *)svsutil_GetFixed (gpState->pfmdPorts);
if (! p) {
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
p->hProcOwner = GetOwnerProcess ();
p->mtu = usInMTU;
p->psm = usPSM;
p->pNext = gpState->pPorts;
gpState->pPorts = p;
gpState->Unlock ();
return ERROR_SUCCESS;
}
int L2CAPAccept
(
unsigned short usPSM, // =>
BT_ADDR *pbt, // <=
unsigned short *pusCID, // <=
unsigned short *pusOutMTU // <=
) {
if (usPSM == 0)
return ERROR_INVALID_PARAMETER;
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = gpState->pCalls;
while (pCall && ((pCall->fWhat != CALL_L2CAP_LINK_SETUP) || (! pCall->fComplete) || (! pCall->pLink) || (pCall->pLink->psm != usPSM) || (! pCall->pLink->fIncoming)))
pCall = pCall->pNext;
if (pCall) {
SVSUTIL_ASSERT (pCall->fAutoClean);
Link *pLink = pCall->pLink;
DeleteCall (pCall);
*pusCID = pLink->cid;
*pusOutMTU = pLink->outMTU;
*pbt = SET_NAP_SAP(pLink->b.NAP, pLink->b.SAP);
gpState->Unlock ();
return ERROR_SUCCESS;
}
Port *p = gpState->pPorts;
while (p && (p->psm != usPSM))
p = p->pNext;
if (! p) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
pCall = AllocCall (CALL_L2CAP_ACCEPT, NULL, GetOwnerProcess());
if (! pCall) {
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
pCall->psm = usPSM;
HANDLE hEvent = pCall->hEvent;
gpState->Unlock ();
WaitForSingleObject (hEvent, INFINITE);
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (pCall != VerifyCall (pCall)) {
gpState->Unlock ();
return ERROR_CANCELLED;
}
Link *pLink = pCall->pLink;
int iRes = pCall->fComplete ? pCall->iResult : ERROR_TIMEOUT;
DeleteCall (pCall);
if (pLink) {
*pusCID = pLink->cid;
*pusOutMTU = pLink->outMTU;
*pbt = SET_NAP_SAP(pLink->b.NAP, pLink->b.SAP);
}
gpState->Unlock ();
return iRes;
}
int L2CAPClosePSM (unsigned short usPSM) {
if (usPSM == 0)
return ERROR_INVALID_PARAMETER;
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Port *pParent = NULL;
Port *p = gpState->pPorts;
while (p && (p->psm != usPSM)) {
pParent = p;
p = p->pNext;
}
if (! p) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
if (pParent)
pParent->pNext = p->pNext;
else
gpState->pPorts = p->pNext;
svsutil_FreeFixed (p, gpState->pfmdPorts);
SCall *pCall = gpState->pCalls;
while (pCall) {
if (pCall->psm == usPSM) {
SVSUTIL_ASSERT (! pCall->fAutoClean);
SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_ACCEPT);
SVSUTIL_ASSERT (pCall->hEvent);
SVSUTIL_ASSERT (pCall->hProcOwner);
SVSUTIL_ASSERT (! pCall->pBuffer);
if (! pCall->fComplete) {
SVSUTIL_ASSERT (! pCall->pLink);
pCall->fComplete = TRUE;
pCall->iResult = ERROR_CANCELLED;
SetEvent (pCall->hEvent);
}
}
pCall = pCall->pNext;
}
HANDLE h = gpState->hL2CAP;
BT_LAYER_IO_CONTROL pCallback = gpState->l2cap_if.l2ca_ioctl;
int iRes = ERROR_INTERNAL_ERROR;
gpState->Unlock ();
__try {
iRes = pCallback (h, BTH_STACK_IOCTL_FREE_PORT, sizeof(usPSM), (char *)&usPSM, 0, NULL, NULL);
} __except (1) {
}
return iRes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -