📄 bthlink.cxx
字号:
return ERROR_SUCCESS;
}
//
// Events, HCI
//
static int bthlink_ConnectionCompleteEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, BD_ADDR *pba, unsigned char link_type, unsigned char encryption_mode) {
if (! gpLayerState)
return ERROR_SERVICE_NOT_ACTIVE;
gpLayerState->Lock ();
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ConnectionComplete :: call 0x%08x, status 0x%02x handle 0x%04x\n", pCallContext, status, connection_handle));
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ConnectionComplete :: shutting down\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = RemoveCallFromList (pCallContext);
if (! pCall) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ConnectionComplete :: no context\n"));
gpLayerState->Unlock ();
return ERROR_NOT_FOUND;
}
if (status == 0) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ConnectionComplete :: creating link\n"));
Link *pLink = new Link;
if (pLink) {
pLink->b = *pba;
pLink->h = connection_handle;
pLink->hProcOwner = pCall->hProcOwner;
pLink->pNext = gpLayerState->pLinks;
gpLayerState->pLinks = pLink;
}
}
pCall->iResult = StatusToError (status, ERROR_PROTOCOL_UNREACHABLE);
pCall->pNext = NULL;
SetEvent (pCall->hEvent);
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ConnectionComplete :: Completed call 0x%08x\n", pCall));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int bthlink_DisconnectionCompleteEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned char reason) {
if (! gpLayerState)
return ERROR_SERVICE_NOT_ACTIVE;
gpLayerState->Lock ();
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DisconnectionComplete :: call 0x%08x, status 0x%02x handle 0x%04x\n", pCallContext, status, connection_handle));
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DisconnectionComplete :: shutting down\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
if (status == 0) {
Link *pLink = gpLayerState->pLinks;
Link *pParent = NULL;
while (pLink && (pLink->h != connection_handle)) {
pParent = pLink;
pLink = pLink->pNext;
}
if (pLink) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DisconnectionComplete :: retured link 0x%04x\n", connection_handle));
if (pParent)
pParent->pNext = pLink->pNext;
else
gpLayerState->pLinks = pLink->pNext;
delete pLink;
}
}
SCall *pCall = RemoveCallFromList (pCallContext);
if (! pCall) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DisconnectionComplete :: no context\n"));
gpLayerState->Unlock ();
return ERROR_NOT_FOUND;
}
pCall->iResult = StatusToError (status, ERROR_PROTOCOL_UNREACHABLE);
pCall->pNext = NULL;
SetEvent (pCall->hEvent);
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DisconnectionComplete :: Completed call 0x%08x\n", pCall));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int bthlink_hStackEvent (void *pUserContext, int iEvent, void *pEventContext) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: Stack EVENT :: %s\n", iEvent == BTH_STACK_DISCONNECT ? L"BTH_STACK_DISCONNECT" : (iEvent == BTH_STACK_DOWN ? L"BTH_STACK_DOWN" : (iEvent == BTH_STACK_UP ? L"UP" : L"Unknown"))));
if (iEvent == BTH_STACK_DISCONNECT)
CloseHandle (CreateThread (NULL, 0, StackDisconnect, NULL, 0, NULL));
else if (iEvent == BTH_STACK_DOWN)
CloseHandle (CreateThread (NULL, 0, StackDown, NULL, 0, NULL));
else if (iEvent == BTH_STACK_UP)
CloseHandle (CreateThread (NULL, 0, StackUp, NULL, 0, NULL));
return ERROR_SUCCESS;
}
static int bthlink_CreateDriverInstance (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CreateInstance\n"));
if (gpLayerState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CreateInstance :: ERROR_ALREADY_INITIALIZED\n"));
return ERROR_ALREADY_INITIALIZED;
}
gpLayerState = CreateNewState ();
if ((! gpLayerState) || (! gpLayerState->fIsRunning)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CreateInstance :: ERROR_OUTOFMEMORY\n"));
if (gpLayerState)
delete gpLayerState;
gpLayerState = NULL;
return ERROR_OUTOFMEMORY;
}
GetConnectionState ();
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CreateInstance :: ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
static int bthlink_CloseDriverInstance (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CloseInstance\n"));
if (! gpLayerState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CloseInstance :: ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpLayerState->Lock ();
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CloseInstance :: ERROR_SERVICE_NOT_ACTIVE\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpLayerState->fIsRunning = FALSE;
while (gpLayerState->GetRefCount () > 1) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CloseInstance :: Sleeping...\n"));
gpLayerState->Unlock ();
Sleep (200);
gpLayerState->Lock ();
}
Link *pLink = gpLayerState->pLinks;
while (gpLayerState->pLinks) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CloseInstance :: Deleting link 0x%04x\n", gpLayerState->pLinks->h));
Link *pNext = gpLayerState->pLinks->pNext;
delete gpLayerState->pLinks;
gpLayerState->pLinks = pNext;
}
SCall *pC = gpLayerState->pCalls;
gpLayerState->pCalls = NULL;
while (pC) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CloseInstance :: Aborting call 0x%08x\n", pC));
SCall *pNext = pC->pNext;
pC->iResult = ERROR_SHUTDOWN_IN_PROGRESS;
pC->pNext = NULL;
SetEvent (pC->hEvent);
pC = pNext;
}
gpLayerState->Unlock ();
delete gpLayerState;
gpLayerState = NULL;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CloseInstance :: ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
static int Connect (BD_ADDR *pba, unsigned short *phandle) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x\n", pba->NAP, pba->SAP));
if (! gpLayerState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: ERROR_SERVICE_NOT_ACTIVE\n", pba->NAP, pba->SAP));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpLayerState->Lock ();
if (! (gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: ERROR_SERVICE_NOT_ACTIVE\n", pba->NAP, pba->SAP));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = new SCall;
if (! pCall) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: ERROR_OUTOFMEMORY\n", pba->NAP, pba->SAP));
gpLayerState->Unlock ();
return ERROR_OUTOFMEMORY;
}
pCall->fWhat = CALL_HCI_CONNECT;
pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
pCall->hProcOwner = GetCallerProcess ();
pCall->pNext = gpLayerState->pCalls;
gpLayerState->pCalls = pCall;
HCI_CreateConnection_In pCallback = gpLayerState->hci_if.hci_CreateConnection_In;
HANDLE hHCI = gpLayerState->hHCI;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: created call 0x%08x\n", pba->NAP, pba->SAP, pCall));
gpLayerState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (hHCI, pCall, pba, BT_PACKET_TYPE_DM1 | BT_PACKET_TYPE_DM3 | BT_PACKET_TYPE_DM5, 0, 0, 0, 1);
} __except (1) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT :: exception in hci_CreateConnection_In\n"));
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (pCall->hEvent, INFINITE);
CloseHandle (pCall->hEvent);
if (! gpLayerState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: ERROR_SHUTDOWN_IN_PROGRESS\n", pba->NAP, pba->SAP));
delete pCall;
return ERROR_SHUTDOWN_IN_PROGRESS;
}
gpLayerState->Lock ();
if (iRes == ERROR_SUCCESS) {
iRes = pCall->iResult;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: call 0x%08x : call result %d\n", pba->NAP, pba->SAP, pCall, iRes));
} else
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: call 0x%08x : immediately returned %d\n", pba->NAP, pba->SAP, pCall, iRes));
RemoveCallFromList (pCall);
delete pCall;
if (iRes == ERROR_SUCCESS) {
if (gpLayerState->fConnected && gpLayerState->fIsRunning) {
Link *pLink = gpLayerState->pLinks;
while (pLink && (pLink->b != *pba))
pLink = pLink->pNext;
if (pLink) {
*phandle = pLink->h;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: success - handle 0x%04x\n", pba->NAP, pba->SAP, pLink->h));
} else {
iRes = ERROR_PROTOCOL_UNREACHABLE;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: ERROR_PROTOCOL_UNREACHABLE\n", pba->NAP, pba->SAP));
}
} else {
iRes = ERROR_SHUTDOWN_IN_PROGRESS;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: CONNECT %04x%08x :: ERROR_SHUTDOWN_IN_PROGRESS\n", pba->NAP, pba->SAP));
}
}
gpLayerState->Unlock ();
return iRes;
}
static int Disconnect (unsigned short handle) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT 0x%04x\n", handle));
if (! gpLayerState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT 0x%04x\n : ERROR_SERVICE_NOT_ACTIVE", handle));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpLayerState->Lock ();
if (! (gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT 0x%04x\n : ERROR_SERVICE_NOT_ACTIVE", handle));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = new SCall;
if (! pCall) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT 0x%04x\n : ERROR_OUTOFMEMORY", handle));
gpLayerState->Unlock ();
return ERROR_OUTOFMEMORY;
}
pCall->fWhat = CALL_HCI_DISCONNECT;
pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
pCall->hProcOwner = GetCallerProcess ();
pCall->pNext = gpLayerState->pCalls;
gpLayerState->pCalls = pCall;
HCI_Disconnect_In pCallback = gpLayerState->hci_if.hci_Disconnect_In;
HANDLE hHCI = gpLayerState->hHCI;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT 0x%04x :: created call 0x%08x\n", handle, pCall));
gpLayerState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (hHCI, pCall, handle, 0x13);
} __except (1) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT :: exception in hci_Disconnect_In\n"));
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (pCall->hEvent, INFINITE);
CloseHandle (pCall->hEvent);
if (! gpLayerState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT 0x%04x :: ERROR_SHUTDOWN_IN_PROGRESS\n", handle));
delete pCall;
return ERROR_SHUTDOWN_IN_PROGRESS;
}
gpLayerState->Lock ();
if (iRes == ERROR_SUCCESS)
iRes = pCall->iResult;
RemoveCallFromList (pCall);
delete pCall;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: DISCONNECT 0x%04x :: %d\n", handle, iRes));
gpLayerState->Unlock ();
return iRes;
}
static int ScoConnect (BD_ADDR* pbaddr, unsigned short* phScoConnection) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect 0x%08x\n", pbaddr));
if (!gpLayerState) {
return ERROR_SERVICE_DOES_NOT_EXIST;
}
if ((! phScoConnection) || (! pbaddr)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect via ACL 0x%08x 0x%08x :: ERROR_INVALID_PARAMETER\n", pbaddr, phScoConnection));
return ERROR_INVALID_PARAMETER;
}
gpLayerState->Lock ();
if (! (gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect via ACL 0x%08x 0x%08x :: ERROR_SERVICE_NOT_ACTIVE\n", pbaddr, phScoConnection));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
// Get a list of ACL connections
BT_LAYER_IO_CONTROL pHCIIoctl = gpLayerState->hci_if.hci_ioctl;
BASEBAND_CONNECTION_DATA ConnData[MAX_BASEBAND_CONNECTIONS];
HANDLE hHCI = gpLayerState->hHCI;
int iRet = ERROR_CALL_NOT_IMPLEMENTED;
int iRetLen = 0;
int iOutBuffer = MAX_BASEBAND_CONNECTIONS * sizeof(BASEBAND_CONNECTION_DATA);
char* pOutBuffer = (char*) ConnData;
gpLayerState->Unlock ();
if (!pHCIIoctl) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: FindAclConnection :: ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_CALL_NOT_IMPLEMENTED;
}
__try {
iRet = pHCIIoctl (hHCI, BTH_HCI_IOCTL_GET_BASEBAND_CONNECTIONS, 0, NULL, iOutBuffer, pOutBuffer, &iRetLen);
} __except (1) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: FindAclConnection :: exception in hci_ioctl BTH_HCI_IOCTL_GET_BASEBAND_CONNECTIONS\n"));
}
if (iRet != ERROR_SUCCESS) {
return iRet;
}
gpLayerState->Lock ();
DWORD dwConnections = iRetLen / sizeof(BASEBAND_CONNECTION_DATA);
// Find the ACL connection to the remote device
BASEBAND_CONNECTION_DATA* pTargetData = NULL;
DWORD dw;
for (dw = 0; dw < dwConnections; dw++) {
if ( (ConnData[dw].baAddress == *pbaddr) && (ConnData[dw].fLinkType == BT_LINK_TYPE_ACL) ) {
pTargetData = &ConnData[dw];
break;
}
}
if (!pTargetData) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: FindAclConnection :: ACL connection to target address %04x%08x not found", pbaddr->NAP, pbaddr->SAP));
gpLayerState->Unlock ();
return ERROR_CONNECTION_INVALID;
}
unsigned short hAclConnection = pTargetData->hConnection;
SCall *pCall = new SCall;
if (! pCall) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect 0x%08x 0x%08x : ERROR_OUTOFMEMORY\n", pbaddr, phScoConnection));
gpLayerState->Unlock ();
return ERROR_OUTOFMEMORY;
}
pCall->fWhat = CALL_HCI_CONNECT;
pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
pCall->hProcOwner = GetCallerProcess ();
pCall->pNext = gpLayerState->pCalls;
gpLayerState->pCalls = pCall;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect via ACL :: created call 0x%08x\n", pCall));
HCI_AddSCOConnection_In pCallback = gpLayerState->hci_if.hci_AddSCOConnection_In;
hHCI = gpLayerState->hHCI;
int iRes = ERROR_INTERNAL_ERROR;
gpLayerState->Unlock ();
__try {
iRes = pCallback (hHCI, pCall, hAclConnection, BT_PACKET_TYPE_HV1|BT_PACKET_TYPE_HV2|BT_PACKET_TYPE_HV3);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTHLINK :: ScoConnect :: exception in hci_AddSCOConnection_In\n"));
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (pCall->hEvent, INFINITE);
CloseHandle (pCall->hEvent);
if (! gpLayerState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect 0x%08x 0x%08x :: ERROR_SHUTDOWN_IN_PROGRESS\n", pbaddr, phScoConnection));
delete pCall;
return ERROR_SHUTDOWN_IN_PROGRESS;
}
gpLayerState->Lock ();
if (iRes == ERROR_SUCCESS) {
iRes = pCall->iResult;
}
if (iRes == ERROR_SUCCESS) {
if (gpLayerState->fConnected && gpLayerState->fIsRunning) {
Link *pLink = gpLayerState->pLinks;
while (pLink && (pLink->b != *pbaddr))
pLink = pLink->pNext;
if (pLink) {
*phScoConnection = pLink->h;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect %04x%08x :: success - handle 0x%04x\n", pbaddr->NAP, pbaddr->SAP, pLink->h));
} else {
iRes = ERROR_PROTOCOL_UNREACHABLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -