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

📄 bthid.cxx

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

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

			return ERROR_SERVICE_NOT_ACTIVE;
		}

		if (! VerifyDevice (pDev)) {
			gpState->Unlock ();

			return ERROR_SERVICE_NOT_ACTIVE;
		}

		BTHHIDPacket *pPacket = pDev->pktTransResp;
		pDev->pktTransResp = NULL;
		pDev->fTrans = FALSE;	// Clear the transaction

		if (! pPacket) {
			gpState->Unlock ();

			return iRes == ERROR_SUCCESS ? ERROR_TIMEOUT : iRes;
		}

		if (ppRes)
			*ppRes = pPacket;
		else {
			pPacket->ReleasePayload ();
			delete pPacket;
		}

		gpState->Unlock ();

		break;
	}

    return iRes;
}

int HidDevice::FillPersistentParameters (int fIncoming) {
	DWORD dwDeviceFlags = 0;
	unsigned char *psdp = NULL;
	unsigned int csdp = 0;

	if (! GetDeviceConfig (&b, &dwDeviceFlags, &psdp, &csdp)) {
	    IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - bonding does not exist\n", b.NAP, b.SAP));
		return FALSE;
	}

	if (fIncoming && ((dwDeviceFlags & HIDCONF_FLAGS_ACTIVE) == 0)) {
	    IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - device is not activated\n", b.NAP, b.SAP));
		g_funcFree (psdp, g_pvFreeData);
		return FALSE;
	}

	if (dwDeviceFlags & HIDCONF_FLAGS_AUTH)
		fAuthenticate = TRUE;

	if (dwDeviceFlags & HIDCONF_FLAGS_ENCRYPT)
		fEncrypt = TRUE;

	BTHHIDSdpParser sdpParser;

    int iErr = sdpParser.Start (psdp, csdp);

	BOOL bb = FALSE;

    if (iErr == ERROR_SUCCESS)
	    iErr = sdpParser.GetHIDReconnectInitiate(&bb);

    if (iErr == ERROR_SUCCESS) {
		fReconnectInitiate = bb;
		iErr = sdpParser.GetHIDNormallyConnectable(&bb);
		if (iErr == ERROR_SUCCESS)
			fNormallyConnectable = bb;
		iErr = ERROR_SUCCESS;
	}

    if (iErr == ERROR_SUCCESS) {
		iErr = sdpParser.GetHIDVirtualCable(&bb);
	}

    // Pass in an empty structure to retrieve the size of the blob
    BLOB blobReportDescriptor = {0, NULL};

    if (iErr == ERROR_SUCCESS) {
		fVirtualCable = bb;
	    iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);
	}

	if (iErr == ERROR_SUCCESS) {
	    // Now we have the size. Allocate and requery.
	    SVSUTIL_ASSERT(blobReportDescriptor.cbSize > 0);
		blobReportDescriptor.pBlobData = (unsigned char *)g_funcAlloc (blobReportDescriptor.cbSize, g_pvAllocData);
		iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);

		if (iErr == ERROR_SUCCESS) {
			iErr = pHidParser->SetReportDescriptor(blobReportDescriptor.pBlobData, blobReportDescriptor.cbSize);
			g_funcFree (blobReportDescriptor.pBlobData, g_pvFreeData);
		}
	}

	sdpParser.End ();

	if (iErr != ERROR_SUCCESS) {
		IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - parsing SDP record failed\n", b.NAP, b.SAP));
	}

	g_funcFree (psdp, g_pvFreeData);

    return iErr == ERROR_SUCCESS;
}

static int ProcessHidPacket (BTHHIDPacket *pPacket, HidDevice *pDev) {
	if (pPacket->GetReportType () == BTHID_REPORT_INPUT) {
		BYTE* pPayload;
		int   cbPayload;

		pPacket->GetPayload(&pPayload, &cbPayload);
		pDev->pHidParser->ProcessInterruptReport(pPayload, cbPayload);
	} else {
	    if (pPacket->GetHeader() == gbUnplugHeader) {
			IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ReportHandler : virtual disconnect\n"));
			// We'll be unloaded really soon. Clean up.
			// ???DisconnectDevice (pDev);
		} else {
			if (! pDev->fTrans) {
				IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - control packet w/o transaction. Aborting...\n"));
				DisconnectDevice (pDev);
			} else {
				if (pDev->pktTransResp) {                        // Transaction violated
					IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - multiple control packets for transaction. Aborting...\n"));
					DisconnectDevice (pDev);
				} else {
					pDev->pktTransResp = pPacket;
					SetEvent (pDev->hevtTrans);
					return FALSE;	// Don't destroy the packet
				}
			}
		}
	}

	return TRUE;
}

//
//	L2CAP stuff
//
static int hiddev_DataUpInd (void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Data up on channel 0x%04x %d bytes\n", cid, BufferTotal (pBuffer)));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	Link *pLink = FindLink (cid);
	HidDevice *pDev = pLink ? FindDevice (&pLink->b) : NULL;
	BTHHIDPacket *pPacket = pDev ? (pLink->psm == BTH_PSM_CONTROL ? pDev->pktControl : pDev->pktInterrupt) : NULL;

	if (pDev && (! pPacket)) {
		pPacket = new BTHHIDPacket;

		if (pPacket) {
			pPacket->SetMTU (pLink->mtu);
			pPacket->SetOwner (pDev);

			if (pLink->psm == BTH_PSM_CONTROL) {
				pPacket->SetReportType(BTHID_REPORT_FEATURE);
				pDev->pktControl = pPacket;
			} else {
				pPacket->SetReportType(BTHID_REPORT_INPUT);
				pDev->pktInterrupt = pPacket;
			}
		}
	}

#if defined (DEBUG) || defined (_DEBUG)
	if (pPacket) {
		SVSUTIL_ASSERT (pPacket->GetOwner() == pDev);
	} else {
		IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Data up - no packet\n"));
	}
#endif

    if (pPacket) {
		if (! pPacket->AddPayloadChunk(pBuffer->pBuffer + pBuffer->cStart, BufferTotal (pBuffer))) {	// finished
			if (pLink->psm == BTH_PSM_CONTROL)
				pDev->pktControl = NULL;
			else
				pDev->pktInterrupt = NULL;

#if defined (BTHHID_QUEUE)
			if (! gpState->qHidReports.Put (pPacket)) {
				pPacket->ReleasePayload();
                delete pPacket;
			}

			SetEvent (gpState->hevtReports);
#else
			int fRelease = ProcessHidPacket (pPacket, pDev);
			if (fRelease) {
				pPacket->ReleasePayload();
				delete pPacket;
			}
#endif
		}
	}


	if (pBuffer->pFree)
		pBuffer->pFree (pBuffer);

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

static int hiddev_DisconnectInd (void *pUserContext, unsigned short cid, int iError) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Disconnect indicator on channel 0x%04x\n", cid));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	Link *pLink = FindLink (cid);
	if (! pLink) {
		gpState->Unlock ();
		return ERROR_NOT_FOUND;
	}

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

		pC = pC->pNext;
	}

	DeleteLink (pLink);

	gpState->Unlock ();
	return ERROR_SUCCESS;
}

static int hiddev_lStackEvent (void *pUserContext, int iEvent, void *pEventContext) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Stack event (L2CAP) %d\n", iEvent));

	if (! gpState)
		return ERROR_SUCCESS;

	gpState->Lock ();

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

	LPTHREAD_START_ROUTINE p = NULL;

	if (iEvent == BTH_STACK_DISCONNECT)
		hiddev_CloseDriverInstance ();
	else if (iEvent == BTH_STACK_DOWN)
		p = StackDown;
	else if (iEvent == BTH_STACK_UP)
		p = StackUp;

	HANDLE h = p ? CreateThread (NULL, 0, p, NULL, 0, NULL) : NULL;

	if (h) {
		CloseHandle (h);
		gpState->AddRef ();
	}

	gpState->Unlock ();

	return ERROR_SUCCESS;
}

static int hiddev_lCallAborted (void *pCallContext, int iError) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Aborted call 0x%08x error %d\n", pCallContext, iError));

	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) {
		IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Aborted call not found!\n"));
		gpState->Unlock ();
		return ERROR_NOT_FOUND;
	}

	SVSUTIL_ASSERT (! pCall->fComplete);
	SVSUTIL_ASSERT (! pCall->pBuffer);

	Link *pLink = pCall->pLink;

	if (pCall->fAutoClean)
		DeleteCall (pCall);
	else {
		pCall->iResult = iError;
		pCall->fComplete = TRUE;
		pCall->pLink = NULL;
		SetEvent (pCall->hEvent);
	}

	unsigned short disconnect_cid = 0;

	if (pLink) {
		if ((pLink->fStage & UP) != UP) {
			if (pLink->fStage & CONNECTED)
				disconnect_cid = pLink->cid;
			else 
				DeleteLink (pLink);
		} else {
			disconnect_cid = pLink->cid;
			pLink->fStage |= LINK_ERROR;
		}
	}

	gpState->Unlock ();

	if (disconnect_cid)
		HIDCloseCID_Int (disconnect_cid);

	return ERROR_SUCCESS;
}

static int hiddev_ConfigInd (void *pUserContext, unsigned char id, unsigned short cid, unsigned short usOutMTU, unsigned short usInFlushTO, struct btFLOWSPEC *pInFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Config request indicator on ch 0x%04x id %d MTU %d flush 0x%04x, flow: %s\n", cid, id, usOutMTU, usInFlushTO, pInFlow ? L"yes" : L"no"));

	if (! gpState)
		return ERROR_SERVICE_NOT_ACTIVE;

	gpState->Lock ();

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

	Link *pLink = FindLink (cid);
	SCall *pCall = pLink ? FindCall (pLink, CALL_L2CAP_LINK_SETUP) : NULL;

	if ((! pCall) || pCall->fComplete)  {
		IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: config setup call not found!\n"));
		gpState->Unlock ();
		return ERROR_NOT_FOUND;
	}

	pCall->l2cap_id = id;

	SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
	SVSUTIL_ASSERT (! pCall->fComplete);
	SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
	SVSUTIL_ASSERT (! pCall->pBuffer);

	int fAccept = FALSE;

//	if ((usInFlushTO == 0xffff) && (! pInFlow)) {
		pCall->iResult = ERROR_SUCCESS;
		pCall->pLink->fStage |= CONFIG_IND_DONE;
		pCall->pLink->mtu = usOutMTU;
		fAccept = TRUE;

		if (pLink->fStage == UP) {
			pCall->fComplete = TRUE;
			pCall->iResult = ERROR_SUCCESS;
			SetEvent (pCall->hEvent);

			if (pCall->fAutoClean)
				DeleteCall (pCall);

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

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

				if (pDev->fHaveControl && pDev->fHaveInterrupt) {
					IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: device %04x%08x connected!\n", pDev->b.NAP, pDev->b.SAP));

					if (pDev->ckConnectionTimeout) {
						gpState->pSchedule->UnScheduleEvent (pDev->ckConnectionTimeout);
						pDev->ckConnectionTimeout = 0;
					}
				} 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"));
				fAccept = FALSE;
			}
		}
//	} else {
//		IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: not accepting config because of flow control parameters.\n"));
//	}

	HANDLE hL2CAP = gpState->hL2CAP;
	L2CA_ConfigResponse_In pCallback = gpState->l2cap_if.l2ca_ConfigResponse_In;
	gpState->Unlock ();

	__try {
		pCallback (hL2CAP, NULL, id, cid, fAccept ? 0 : 2, 0, 0xffff, NULL, 0, NULL);
	} __except (1) {
	}

	if (! fAccept)
		hiddev_lCallAborted (pCall, ERROR_CONNECTION_ABORTED);

	return ERROR_SUCCESS;
}

static int hiddev_ConfigReq_Out (void *pCallContext, unsigned short usResult, unsigned short usInMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Config req out for call 0x%08x result 0x%04x mtu %d flush 0x%04x, flow %s\n", pCallContext, usResult, usInMTU, usOutFlushTO, pOutFlow ? L"yes" : L"no" ));

	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)  {
		IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: config setup call not found!\n"));
		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 (usResult == 0) {
		Link *pLink = pCall->pLink;
		SVSUTIL_ASSERT (! (pLink->fStage & CONFIG_REQ_DONE));
		SVSUTIL_ASSERT (pLink->fStage & CONNECTED);
		SVSUTIL_ASSERT (pLink->cid);
		SVSUTIL_ASSERT (pLink->psm);

		pLink->fStage |= CONFIG_REQ_DONE;

		if (pLink->fStage == UP) {
			pCall->fComplete = TRUE;
			pCall->iResult = ERROR_SUCCESS;
			SetEvent (pCall->hEvent);

			if (pCall->fAutoClean)
				DeleteCall (pCall);

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

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

				if (pDev->fHaveControl && pDev->fHaveInterrupt) {
					IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: device %04x%08x connected!\n", pDev->b.NAP, pDev->b.SAP));

					if (pDev->ckConnectionTimeout) {
						gpState->pSchedule->UnScheduleEvent (pDev->ckConnectionTimeout);
						pDev->ckConnectionTimeout = 0;
					}

⌨️ 快捷键说明

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