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

📄 bthid.cxx

📁 CE下基于PXA255的蓝牙驱动
💻 CXX
📖 第 1 页 / 共 5 页
字号:
				} else if (! pDev->ckConnectionTimeout)
					pDev->ckConnectionTimeout = gpState->pSchedule->ScheduleEvent (ConnectionTimeout, pDev, BTH_CONNECTION_TIMEOUT);
			} else {
				IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: could not find HID device - connection not accepted!\n"));

				gpState->Unlock ();

				hiddev_lCallAborted (pCallContext, ERROR_CONNECTION_ABORTED);

				return ERROR_SUCCESS;
			}
		}

		gpState->Unlock ();
		return ERROR_SUCCESS;
	}

	gpState->Unlock ();

	hiddev_lCallAborted (pCallContext, ERROR_CONNECTION_ABORTED);

	return ERROR_SUCCESS;
}

static int hiddev_ConnectInd (void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connect indicator from %04x%08x ch 0x%04x id %d psm 0x%04x\n", pba->NAP, pba->SAP, cid, id, psm));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

	if (! gpState->fIsRunning) {
		gpState->Unlock ();
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	unsigned short	result = 0;
	unsigned short	status = 0;

	HidDevice *pDev = FindDevice (pba);

	if (! pDev)
		pDev = MakeNewDevice (pba, TRUE);

	if (! pDev) {
		IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: connect indication: could not make device\n"));
		result = 4;
	} else if (pDev->ckDeviceTimeout) {
		gpState->pSchedule->UnScheduleEvent (pDev->ckDeviceTimeout);
		pDev->ckDeviceTimeout = 0;
	}

	SCall *pCall = NULL;

	if (pDev) {
    	Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
	    pCall = pLink ? AllocCall (CALL_L2CAP_LINK_SETUP, pLink) : NULL;
	    if (pCall) {
		    pCall->fAutoClean = TRUE;
			pCall->l2cap_id = id;

		    pLink->b = *pba;
		    pLink->cid = cid;
		    pLink->fStage = CONNECTED;
		    pLink->mtu = 0;
		    pLink->psm = psm;
		    pLink->fIncoming = TRUE;

		    pLink->pNext = gpState->pLinks;
		    gpState->pLinks = pLink;

		    result = 0;
		} else {
			if (pLink)
				svsutil_FreeFixed (pLink, gpState->pfmdLinks);
			result = 4;
		}
	} else {
		if (result == 0)
			result = 2;
	}

	if ((result == 0) && (pDev->fEncrypt || pDev->fAuthenticate) && (! pDev->fAuthSpinned)) {
		pDev->fAuthSpinned = TRUE;
		gpState->pSchedule->ScheduleEvent (AuthenticateDevice, pCall, 0);

		gpState->Unlock ();

		return ERROR_SUCCESS;
	}

	HANDLE hL2CAP = gpState->hL2CAP;
	L2CA_ConnectResponse_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectResponse_In;
	L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
	gpState->Unlock ();

	__try {
		pCallbackConnect (hL2CAP, NULL, pba, id, cid, result, status);
	} __except (1) {
	}

	if (result == 0) {
		int iRes = ERROR_INTERNAL_ERROR;
		__try {
			iRes = pCallbackConfig (hL2CAP, pCall, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
		} __except (1) {
		}

		if (iRes != ERROR_SUCCESS)
			hiddev_lCallAborted (pCall, iRes);
	}

	return ERROR_SUCCESS;
}

static int hiddev_ConnectReq_Out (void *pCallContext, unsigned short cid, unsigned short result, unsigned short status) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connect out for call 0x%08x ch 0x%04x result = 0x%04x status 0x%04x\n", pCallContext, cid, result, status));

	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_LINK_SETUP);
	SVSUTIL_ASSERT (! pCall->fComplete);
	SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
	SVSUTIL_ASSERT (! pCall->pBuffer);

	if (result) {
		if (result != 1) {
			pCall->fComplete = TRUE;
			pCall->iResult = ERROR_CONNECTION_REFUSED;
			SetEvent (pCall->hEvent);
		}
		gpState->Unlock ();
		return ERROR_SUCCESS;
	}

	HidDevice *pDev = FindDevice (&pCall->pLink->b);

	if (! pDev) {
		pCall->fComplete = TRUE;
		pCall->iResult = ERROR_CONNECTION_REFUSED;
		SetEvent (pCall->hEvent);
		gpState->Unlock ();

		HIDCloseCID_Int (cid);
		return ERROR_SUCCESS;
	}

	Link *pLink = pCall->pLink;

	SVSUTIL_ASSERT (pLink->fStage == NONE);
	SVSUTIL_ASSERT (! pLink->cid);
	SVSUTIL_ASSERT (pLink->psm);

	pLink->fStage = CONNECTED;
	pLink->cid = cid;

	if ((pDev->fEncrypt || pDev->fAuthenticate) && (! pDev->fAuthSpinned)) {
		pDev->fAuthSpinned = TRUE;
		gpState->pSchedule->ScheduleEvent (AuthenticateDevice, pCallContext, 0);

		gpState->Unlock ();

		return ERROR_SUCCESS;
	}

	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, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
	} __except (1) {
	}

	if (iRes != ERROR_SUCCESS)
		hiddev_lCallAborted (pCallContext, iRes);

	return ERROR_SUCCESS;
}

static int hiddev_DataDown_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Data down call 0x%08x result %d\n", pCallContext, result));
	return ERROR_SUCCESS;
}

static int hiddev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: hiddev_Ping_Out call 0x%08x result %d\n", pCallContext));
	return ERROR_SUCCESS;
}

// These are just stubs - they do nothing
static int hiddev_ConfigResponse_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ConfigResponse out call 0x%08x, result %d\n", pCallContext, result));
	return ERROR_SUCCESS;
}

static int hiddev_ConnectResponse_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ConnectResponse out call 0x%08x, result %d\n", pCallContext, result));
	return ERROR_SUCCESS;
}

static int hiddev_Disconnect_Out (void *pCallContext, unsigned short result) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: disconnect out call 0x%08x, result %d\n", pCallContext, result));
	return ERROR_SUCCESS;
}

//
//	Init stuff
//
static int hiddev_CreateDriverInstance (void) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+hiddev_CreateDriverInstance\n"));

	if (gpState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_ALREADY_INITIALIZED\n"));
		return ERROR_ALREADY_INITIALIZED;
	}

	if (! BthPktInitAllocator ())
		return ERROR_OUTOFMEMORY;

	BTHID_Header_Parameter  packetVirtualUnplug;
    packetVirtualUnplug.bRawHeader = 0;

    packetVirtualUnplug.control_p.bControlOp = BTHID_CONTROL_VIRTUAL_CABLE_UNPLUG;
    gbUnplugHeader = (BTHID_HID_CONTROL << 4) | packetVirtualUnplug.bRawHeader;

	gpState = CreateNewState ();

	if ((! gpState) || (! gpState->fIsRunning)) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_OUTOFMEMORY\n"));
		if (gpState)
			delete gpState;
		gpState = NULL;
		return ERROR_OUTOFMEMORY;
	}

#if defined (BTHHID_QUEUE)
    gpState->hthReports = CreateThread (NULL, 0, HidReportHandler, NULL, 0, NULL);
	if (gpState->hthReports)
		SetThreadPriority (gpState->hthReports, THREAD_PRIORITY_HIGHEST);
#endif

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_SUCCESS\n"));
	return ERROR_SUCCESS;
}


static int hiddev_CloseDriverInstance (void) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+hiddev_CloseDriverInstance\n"));

	if (! gpState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpState->Lock ();
	if (! gpState->fIsRunning) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_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 hiddev_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"-hiddev_CloseDriverInstance : ERROR_SUCCESS\n"));

	gpState->Unlock ();
	delete gpState;
	gpState = NULL;

	BthPktFreeAllocator ();

	return ERROR_SUCCESS;
}

#if defined (BTHHID_QUEUE)
//
//	HID reports processing
//
static DWORD WINAPI HidReportHandler (LPVOID lpNull) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ReportHandler : started\n"));

	for ( ; ; ) {
		if (! gpState)
			return 0;

		gpState->Lock ();

		if (! gpState->fIsRunning) {
			gpState->Unlock ();
			break;
		}

		HANDLE hEvent = gpState->hevtReports;

		gpState->Unlock ();

		WaitForSingleObject (hEvent, INFINITE);

		gpState->Lock ();

		if (! gpState->fIsRunning) {
			gpState->Unlock ();
			break;
		}

		while (! gpState->qHidReports.IsEmpty()) {
			BTHHIDPacket *pPacket = (BTHHIDPacket *)gpState->qHidReports.Get ();
			HidDevice *pDev = VerifyDevice ((HidDevice *)pPacket->GetOwner());
			int fRelease = TRUE;
			if (pDev)
				fRelease = ProcessHidPacket (pPacket, pDev);
			else {
				IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: Device not found for a packet...\n"));
			}

			if (fRelease) {
				pPacket->ReleasePayload();
				delete pPacket;
			}
		}
		gpState->Unlock ();
	}
	return 0;
}
#endif

//
//	Internal API section
//

static int HIDConnect_Int
(
BD_ADDR			*pba,
unsigned short  usPSM,
unsigned short  *pusCid
) {
	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->fIncoming = FALSE;
	pLink->psm = usPSM;

	pLink->pNext = gpState->pLinks;
	gpState->pLinks = pLink;

	SCall *pCall = AllocCall (CALL_L2CAP_LINK_SETUP, pLink);
	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)
			HIDCloseCID_Int (cid_disconnect);

		return iRes;
	}

	*pusCid = pLink->cid;

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

static int HIDCloseCID_Int (unsigned short usCID) {
	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	if (! gpState->fIsRunning) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	Link *pLink = FindLink (usCID);
	if (! pLink) {
		gpState->Unlock ();

		return ERROR_NOT_FOUND;
	}

	unsigned short cid = pLink->cid;
	DeleteLink (pLink);
	HANDLE hL2CAP = gpState->hL2CAP;
	L2CA_Disconnect_In pCallback = gpState->l2cap_if.l2ca_Disconnect_In;

	gpState->Unlock ();

	__try {
		pCallback (hL2CAP, NULL, cid);
	} __except (1) {
	}

	return ERROR_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -