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

📄 bthid.cxx

📁 CE下串口复用程序
💻 CXX
📖 第 1 页 / 共 5 页
字号:

	return p;
}

static void DisconnectDevice (HidDevice *pDev) {
	for ( ; ; ) {
		Link *pLink = FindLink (&pDev->b);
		if (! pLink)
			return;

		HIDCloseCID_Int (pLink->cid);
	}
}

static DWORD WINAPI DeviceTimeout (LPVOID lpArg) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Timeout on hid device\n"));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	HidDevice *pDev = VerifyDevice ((HidDevice *)lpArg);
	if (pDev && pDev->ckDeviceTimeout && (! FindLink (&pDev->b))) {
		if (pDev == gpState->pHIDs)
			gpState->pHIDs = pDev->pNext;
		else {
			HidDevice *p = gpState->pHIDs;
			while (p->pNext != pDev)
				p = p->pNext;

			p->pNext = pDev->pNext;
		}

		delete pDev;
	}

	gpState->Unlock ();

	return ERROR_SUCCESS;
}

static DWORD WINAPI ConnectionTimeout (LPVOID lpArg) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connection Timeout on hid device\n"));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	HidDevice *pDev = VerifyDevice ((HidDevice *)lpArg);
	if (pDev && pDev->ckConnectionTimeout && (! (pDev->fHaveControl && pDev->fHaveInterrupt))) {
		pDev->ckConnectionTimeout = 0;
		DisconnectDevice (pDev);
	}

	gpState->Unlock ();

	return ERROR_SUCCESS;
}

static void DeleteLink (Link *pLink) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: delete link for bd_addr %04x%08x cid 0x%04x\n", pLink->b.NAP, pLink->b.SAP, pLink->cid));

	if (pLink == gpState->pLinks)
		gpState->pLinks = pLink->pNext;
	else {
		Link *pParent = gpState->pLinks;
		while (pParent && (pParent->pNext != pLink))
			pParent = pParent->pNext;

		if (! pParent) {
			IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: link to be deleted not in list\n"));
			return;
		}

		pParent->pNext = pLink->pNext;
	}

	SCall *pC = gpState->pCalls;
	while (pC) {
		if (pC->pLink == pLink) {
			if (pC->fAutoClean) {
				DeleteCall (pC);
				pC = gpState->pCalls;
				continue;
			} else if (! pC->fComplete) {
				pC->pLink = NULL;
				pC->fComplete = TRUE;
				pC->iResult = ERROR_CONNECTION_UNAVAIL;
				SetEvent (pC->hEvent);
			} else {
				pC->pLink = NULL;
				if (pC->iResult == ERROR_SUCCESS)
					pC->iResult = ERROR_CONNECTION_UNAVAIL;

			}
		}

		pC = pC->pNext;
	}

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

	if (pDev) {
		if (pLink->psm == BTH_PSM_CONTROL)
			pDev->fHaveControl = FALSE;
		else
			pDev->fHaveInterrupt = FALSE;

		if (! pDev->ckDeviceTimeout)
			pDev->ckDeviceTimeout = gpState->pSchedule->ScheduleEvent (DeviceTimeout, pDev, BTH_PARSER_TIMEOUT);
	}

	svsutil_FreeFixed (pLink, gpState->pfmdLinks);
}

static void HID_BufferFree (BD_BUFFER *pBuf) {
	if (! pBuf->fMustCopy)
		g_funcFree (pBuf, g_pvFreeData);
}

static void HID_BufferFreeArray (BD_BUFFER **ppArray, int carray) {
	for (int i = 0 ; i < carray ; ++i)
		HID_BufferFree (ppArray[i]);
}

static BD_BUFFER *HID_BufferAlloc (int cSize) {
	SVSUTIL_ASSERT (cSize > 0);

	BD_BUFFER *pRes = (BD_BUFFER *)g_funcAlloc (cSize + sizeof (BD_BUFFER), g_pvAllocData);
	pRes->cSize = cSize;

	pRes->cEnd = pRes->cSize;
	pRes->cStart = 0;

	pRes->fMustCopy = FALSE;
	pRes->pFree = HID_BufferFree;
	pRes->pBuffer = (unsigned char *)(pRes + 1);

	return pRes;
}

static BD_BUFFER *HID_BufferCopy (BD_BUFFER *pBuffer) {
	BD_BUFFER *pRes = HID_BufferAlloc (pBuffer->cSize);
	pRes->cSize = pBuffer->cSize;
	pRes->cStart = pBuffer->cStart;
	pRes->cEnd = pBuffer->cEnd;
	pRes->fMustCopy = FALSE;
	pRes->pFree = HID_BufferFree;
	pRes->pBuffer = (unsigned char *)(pRes + 1);

	memcpy (pRes->pBuffer, pBuffer->pBuffer, pRes->cSize);

	return pRes;
}

static DWORD WINAPI StackDown (LPVOID lpVoid) {		// Attention - must increment ref count before calling this!
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Stack Down\n"));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	gpState->DelRef ();

	if ((! gpState->fIsRunning) || (! gpState->fConnected)) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpState->fConnected = FALSE;

    Link *pLink = gpState->pLinks;

	while (gpState->pLinks)
		DeleteLink (gpState->pLinks);

	SCall *pC = gpState->pCalls;
	while (pC) {
		if (pC->fAutoClean) {
			DeleteCall (pC);
			pC = gpState->pCalls;
			continue;
		} else if (! pC->fComplete) {
			pC->pLink = NULL;
			pC->fComplete = TRUE;
			pC->iResult = ERROR_CONNECTION_UNAVAIL;
			SetEvent (pC->hEvent);
		} else {
			pC->pLink = NULL;
			if (pC->iResult == ERROR_SUCCESS)
				pC->iResult = ERROR_CONNECTION_UNAVAIL;
		}
		pC = pC->pNext;
	}

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

static DWORD WINAPI StackUp (LPVOID lpVoid) {	// Attention - must increment ref count before calling this!
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Stack Up\n"));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();
	gpState->DelRef ();

	if ((! gpState->fIsRunning) || gpState->fConnected) {
		gpState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpState->fConnected = TRUE;
	gpState->Unlock ();

	return ERROR_SUCCESS;
}

static void ProcessExited (HANDLE hProc) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ProcessExited 0x%08x\n", hProc));

	if (! gpState)
		return;

	gpState->Lock ();

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

	gpState->Unlock ();
}

static HidDevice *MakeNewDevice (BD_ADDR *pba, int fIncoming) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: MakeNewDevice %04x%08x\n", pba->NAP, pba->SAP));

	HidDevice *pDev = new HidDevice (pba);

	if (! pDev)
		return NULL;

	if (! pDev->FillPersistentParameters (fIncoming)) {
		IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: MakeNewDevice %04x%08x fails to retrieve pairing information\n", pba->NAP, pba->SAP));
		delete pDev;
		return NULL;
	}

	pDev->pNext     = gpState->pHIDs;
	gpState->pHIDs  = pDev;
	pDev->fIncoming = fIncoming;

	return pDev;
}

static DWORD WINAPI AuthenticateDevice (LPVOID lpArg) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request on hid device\n"));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	SCall *pCall = VerifyCall ((SCall *)lpArg);
	HidDevice *pDev = pCall ? FindDevice (&pCall->pLink->b) : NULL;

	if (! pDev) {
		IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: authentication request on nonexistent hid device\n"));
		gpState->Unlock ();

		return ERROR_SUCCESS;
	}

	int fAuth = pDev->fAuthenticate;
	int fEncr = pDev->fEncrypt;
	int fIncoming = pDev->fIncoming;

	unsigned char id = pCall->l2cap_id;
	unsigned short cid = pCall->pLink->cid;

	BD_ADDR b = pDev->b;
	BT_ADDR bt = SET_NAP_SAP (b.NAP, b.SAP);

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request on hid device %04x%08x cid 0x%04x auth: %d, encr: %d, incoming: %d\n", b.NAP, b.SAP, fAuth, fEncr, fIncoming));

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

	gpState->Unlock ();

	if (fIncoming) {
		__try {
			pCallbackConnect (hL2CAP, NULL, &b, id, cid, 1, 1);
		} __except (1) {
		}
	}

	int iErr = ERROR_SUCCESS;
	if (fAuth)
		iErr = BthAuthenticate (&bt);

	if (fEncr && (iErr == ERROR_SUCCESS))
		iErr = BthSetEncryption (&bt, TRUE);

	gpState->Lock ();

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

	pDev = VerifyDevice (pDev);
	if (! pDev) {
		IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: authentication request : device disappeared enroute\n"));
		gpState->Unlock ();

		return ERROR_SUCCESS;
	}

	gpState->Unlock ();

	if (fIncoming) {
		unsigned short result = 0;

		if (iErr != ERROR_SUCCESS)
			result = 3;

		__try {
			pCallbackConnect (hL2CAP, NULL, &b, id, cid, result, 0);
		} __except (1) {
		}

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

		if (iErr != ERROR_SUCCESS)
			hiddev_lCallAborted (pCall, iErr);
	} else {
		if (iErr == ERROR_SUCCESS) {
			iErr = ERROR_INTERNAL_ERROR;
			__try {
				iErr = pCallbackConfig (hL2CAP, pCall, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
			} __except (1) {
			}
		} else
			HIDCloseCID_Int (cid);

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

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request completes with status %d\n", iErr));

	return ERROR_SUCCESS;
}

static int WriteControlPacket (void *lpHidDevice, BTHHIDPacket *pSource, int iTimeout, BTHHIDPacket **ppRes) {
	int iRes = ERROR_SUCCESS;

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

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

			return ERROR_SERVICE_NOT_ACTIVE;
		}

		HidDevice *pDev = VerifyDevice ((HidDevice *)lpHidDevice);
		if (! pDev) {
			gpState->Unlock ();

			return ERROR_SERVICE_NOT_ACTIVE;
		}

		HANDLE hevtComplete = pDev->hevtTransFree;

		if (pDev->fTrans) {	// We don't have the transaction
			gpState->Unlock ();

			if (iTimeout == 0)
				return ERROR_TIMEOUT;

			DWORD dwTicks = GetTickCount ();
			WaitForSingleObject (hevtComplete, iTimeout);
			if (iTimeout != INFINITE) {
				iTimeout -= GetTickCount () - dwTicks;
				if (iTimeout < 0)
					iTimeout = 0;
			}

			continue;
		}

		Link *pLink = FindLink (&pDev->b, BTH_PSM_CONTROL);
		if (! pLink) {
			gpState->Unlock ();

			return ERROR_NOT_FOUND;
		}

		BD_BUFFER *frags[BTH_MAX_FRAGMENTS];
		int cfrags = 0;

		pSource->SetMTU(pLink->mtu);

		for (cfrags = 0 ; cfrags < BTH_MAX_FRAGMENTS ; ++cfrags) {
			int cChunk = 0;
			pSource->GetPayloadChunk (NULL, 0, &cChunk);

			frags[cfrags] = HID_BufferAlloc (cChunk + gpState->cHeaders + gpState->cTrailers);
			if (! frags[cfrags]) {
				HID_BufferFreeArray (frags, cfrags);
				gpState->Unlock ();

				return ERROR_OUTOFMEMORY;
			}

			frags[cfrags]->cStart = gpState->cHeaders;
			frags[cfrags]->cEnd = frags[cfrags]->cSize - gpState->cTrailers;

			if (! pSource->GetPayloadChunk(frags[cfrags]->pBuffer + frags[cfrags]->cStart, cChunk, &cChunk))
				break;
		}

		if (cfrags == BTH_MAX_FRAGMENTS) {
			HID_BufferFreeArray (frags, cfrags);
			gpState->Unlock ();

			return ERROR_OUTOFMEMORY;
		}

		++cfrags;

		HANDLE hL2CAP = gpState->hL2CAP;
		L2CA_DataDown_In pCallback = gpState->l2cap_if.l2ca_DataDown_In;

		unsigned short usCID = pLink->cid;
		HANDLE hevt = pDev->hevtTrans;

		pDev->fTrans = TRUE;	// We own the transaction
		ResetEvent (hevtComplete);

		gpState->Unlock ();

		iRes = ERROR_SUCCESS;
		int iSent = 0;
		__try {
			for (iSent = 0 ; iSent < cfrags ; ++iSent) {
				if (ERROR_SUCCESS != (iRes = pCallback (hL2CAP, NULL, usCID, frags[iSent])))
					break;
			}
		} __except (1) {
			iRes = ERROR_EXCEPTION_IN_SERVICE;
		}

		if (iRes == ERROR_SUCCESS)
			WaitForSingleObject (hevt, iTimeout);

		if (! gpState) {
			SetEvent (hevtComplete);
			return ERROR_SERVICE_NOT_ACTIVE;
		}

		gpState->Lock ();

		if (iRes != ERROR_SUCCESS)
			HID_BufferFreeArray (frags + iSent, cfrags - iSent);

⌨️ 快捷键说明

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