⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bthlink.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 3 页
字号:

	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 + -