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

📄 usbdev.cpp

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

		int fRes = GetBuffer (i, 0, nPacketSize, pBuffer, TRUE);
		SVSUTIL_ASSERT (fRes);

		return TRUE;
	}

	return FALSE;
#endif
}

BOOL CompressBuffer (
	PBYTE	pBuffer,			// in out
	PDWORD	pdwFrameDataLens,	// in
	DWORD	dwFrames,			// in
	DWORD	dwFrameSize,		// in
	PDWORD	pdwCompressedSize	// out
	)
{
	PBYTE pFrame;
	DWORD dw;

	*pdwCompressedSize = 0;

	pFrame = pBuffer;
	for (dw = 0; dw < dwFrames; dw++)
	{
		if (*pdwFrameDataLens > dwFrameSize) {
			return FALSE;
		}
		if ( (pFrame != pBuffer) && *pdwFrameDataLens ) {
			memmove(pBuffer, pFrame, *pdwFrameDataLens);
		}

		pFrame += dwFrameSize;
		pBuffer += *pdwFrameDataLens;
		*pdwCompressedSize += *pdwFrameDataLens;
		pdwFrameDataLens++;
	}

	return TRUE;
}

int CUsbDevice::ReadPacket (unsigned char *pBuffer, int *pnLen, int *pnType)
{
	IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] +ReadPacket\n"));

	for ( ; ; )
	{
		gpsynchUsbDevice->Lock ();

		if (!CheckDevice())
		{
			IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] -ReadPacket : FALSE (device dead)\n"));
			gpsynchUsbDevice->Unlock();
			return FALSE;
		}

		DWORD dwTimeout = INFINITE;

		if (RetrievePacket (pBuffer, pnLen, pnType, &dwTimeout))
		{
#if defined (CONNECTION_TRACKING)
			if ((*pnType == EVENT_INTERRUPT) && (*pnLen > 4)) {
				unsigned short x = pBuffer[3] | (pBuffer[4] << 8);
				if (pBuffer[0] == HCI_Connection_Complete_Event) {
					IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"USB CONNECTION TRACKING : detected connection 0x%04x\n", x));
					if (! _pHandleTree->Locate (x))
						_pHandleTree->Insert (x, (void *)1);
				} else if ((*pnLen > 4) && (pBuffer[0] == HCI_Disconnection_Complete_Event)) {
					IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"USB CONNECTION TRACKING : detected connection drop 0x%04x\n", x));
					SVSTNode *pNode = _pHandleTree->Locate (x);
					if (pNode)
						_pHandleTree->Delete (pNode);
					else {
						IFDBG(DebugOut (DEBUG_ERROR, L"USB CONNECTION TRACKING : handle 0x%08x not found!\n", x));
					}
				} else if ((*pnLen > 5) && (pBuffer[0] == HCI_Command_Complete_Event) && (x == HCI_Reset) && (pBuffer[5] == 0)) {
					IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"USB CONNECTION TRACKING : detected reset\n"));
					_pHandleTree->Empty ();
				}
			}
#endif

#if defined (BT_USE_CELOG)
			if (g_fCeLog) {
				unsigned short usFlag = 0;
				switch (*pnType) {
				case EVENT_BULK:
					usFlag = CELOG_FLAG_HCI_ACL_IN;
					break;
				case EVENT_INTERRUPT:
					usFlag = CELOG_FLAG_HCI_EVENT_IN;
					break;
				case EVENT_ISOCH:
					usFlag = CELOG_FLAG_HCI_SCO_IN;
					break;
				}

				if (usFlag) {
					CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, (unsigned short)*pnLen, 0, CELZONE_ALWAYSON, usFlag);
				}
			}
#endif


			IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] -ReadPacket : TRUE (got stuff) _usbPipes[%d].iTotalQueue=%d\n", 
				*pnType, _usbPipes[*pnType].iTotalQueue));
			gpsynchUsbDevice->Unlock();
			return TRUE;
		}

		HANDLE hEvents[2] = {gheventPackets, gheventClose};

		IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] ReadPacket : WAIT\n"));

		gpsynchUsbDevice->Unlock();
		DWORD dwEvent = WaitForMultipleObjects(2, hEvents, FALSE, dwTimeout);

		if ((dwEvent == WAIT_TIMEOUT) || (dwEvent == WAIT_OBJECT_0))
			continue;

		IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] -ReadPacket : FALSE (device dead)\n"));
		return FALSE;
	}
}

DWORD CALLBACK CUsbDevice::ReadThreadProcStub(LPVOID lpvNotifyParameter)
{
#if defined (DEBUG)
	SVSUTIL_ASSERT(lpvNotifyParameter == gpUsbDevice);
#endif
	
	return(gpUsbDevice->ReadThreadProc());
}

DWORD CUsbDevice::ReadThreadProc(void)
{
	HANDLE hEvents[NUM_IN_PIPES+2];	

	for (int i=0; i<NUM_IN_PIPES; i++)
		hEvents[i] = gheventRead[i];

	hEvents[NUM_IN_PIPES] = gheventClose;
	hEvents[NUM_IN_PIPES+1] = gheventWritten;

	int fStop = FALSE;

	while(TRUE)
	{

		DWORD dwEvent = WaitForMultipleObjects(NUM_IN_PIPES+2, hEvents, FALSE, INFINITE);
		
		if ((dwEvent < WAIT_OBJECT_0) || (dwEvent > WAIT_OBJECT_0 + NUM_IN_PIPES + 2 - 1))
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] ReadThreadProc error in WaitForMultipleObjects... Exiting thread.\n"));
			fStop = TRUE;
			break;
		}

		gpsynchUsbDevice->Lock();

		int nEvent = dwEvent - WAIT_OBJECT_0;

		SVSUTIL_ASSERT(nEvent >= 0 && nEvent <= NUM_IN_PIPES+3);

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"Event %d set.\n", nEvent));

		if (nEvent == EVENT_CLOSE)
		{
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[HCI] [USB] Close event received. Exiting read thread...\n"));
			gpsynchUsbDevice->Unlock();

			break;
		}

		if (!CheckDevice()) 
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Device closed. Exiting read thread...\n"));
			gpsynchUsbDevice->Unlock();

			break;
		}

		if (nEvent == EVENT_WRITTEN) {
			if (ERROR_SUCCESS != gpRingBuffer->CompletePackets ()) {
				IFDBG(DebugOut (DEBUG_WARN, L"[WARN] USB write completed async but could not complete packets.\n"));	
			}

			gpsynchUsbDevice->Unlock();

			continue;
		}

		SVSUTIL_ASSERT(_lpUsbFuncs != NULL);
		PREFAST_ASSERT(_usbPipes[nEvent]._pCurPacket);

		DWORD dwErr = USB_NO_ERROR;
		BOOL fSuccess;

		if (nEvent == EVENT_ISOCH) {
			DWORD dwFrameLens[MAX_SCO_READ_FRAMES_PER_TRANSFER];
			DWORD dwFrameErrors[MAX_SCO_READ_FRAMES_PER_TRANSFER];

			fSuccess = _lpUsbFuncs->lpGetIsochResults ( _usbPipes[nEvent]._hTransfer, 
														_uiSCOReadFrames,
														dwFrameLens,
														dwFrameErrors);
			if (fSuccess) {				
				_usbPipes[nEvent]._pCurPacket->nSize = 0;

				for (DWORD dw = 0; dw < _uiSCOReadFrames; dw++)
				{
					if (dwFrameErrors[dw] != USB_NO_ERROR) {
						dwErr = dwFrameErrors[dw];
						break;
					}
				}
				if (dwErr == USB_NO_ERROR) {
					DWORD dwBytes;
					BOOL bSuc = CompressBuffer ((PBYTE) _usbPipes[nEvent]._pCurPacket->data, 
												dwFrameLens, 
												_uiSCOReadFrames, 
												(DWORD) _endpSCOOut[_nScoPipeIdx].wMaxPacketSize, 
												&dwBytes);
					if (bSuc) {
						_usbPipes[nEvent]._pCurPacket->nSize = (int) dwBytes;
					} else {
						IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Invalid frame data len for isoch transfer. Ignoring transfer...\n"));
					}
				}
			}
		} else {
			fSuccess = _lpUsbFuncs->lpGetTransferStatus(_usbPipes[nEvent]._hTransfer, 
														(DWORD*)&_usbPipes[nEvent]._pCurPacket->nSize, 
														&dwErr);
		}

		if (!fSuccess)
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Invalid USB transfer handle. Exiting thread...\n"));
			gpsynchUsbDevice->Unlock();
			fStop = TRUE;

			break;
		}
		else if (dwErr != USB_NO_ERROR)
		{
			// IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Err %d on event %d. Ignoring...\n", dwErr, nEvent));
		}
		else if (_usbPipes[nEvent]._pCurPacket->nSize == 0)
		{
			if (nEvent!=EVENT_ISOCH) {
				IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Packet size 0 : ignoring \n"));
			}
		}
		else if (_usbPipes[nEvent]._pCurPacket->nSize > (int)_uiPacketSize)
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Invalid Packet size %d : ignoring packet\n", _usbPipes[nEvent]._pCurPacket->nSize));
			SVSUTIL_ASSERT(0);
			_usbPipes[nEvent]._pCurPacket->nSize = 0;
		}
		else
		{
			IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] GetTransferStatus returns %d bytes transferred. Error=%d\n", _usbPipes[nEvent]._pCurPacket->nSize, dwErr));
			DumpBuff(DEBUG_HCI_DUMP, _usbPipes[nEvent]._pCurPacket->data, _usbPipes[nEvent]._pCurPacket->nSize);

			SVSUTIL_ASSERT(_usbPipes[nEvent]._pCurPacket->nSize <= (int)_uiPacketSize);

#if defined (CONNECTION_TRACKING)
			_usbPipes[nEvent]._pCurPacket->dwWhenReceived = GetTickCount ();
#endif

			if (_usbPipes[nEvent]._pLastPacket)
			{
				SVSUTIL_ASSERT(_usbPipes[nEvent]._pLastPacket->pNext == NULL);
				_usbPipes[nEvent]._pLastPacket->pNext = _usbPipes[nEvent]._pCurPacket;
				_usbPipes[nEvent]._pLastPacket = _usbPipes[nEvent]._pCurPacket;
			}
			else
			{
				SVSUTIL_ASSERT(_usbPipes[nEvent]._pPackets == NULL);
				_usbPipes[nEvent]._pLastPacket = _usbPipes[nEvent]._pPackets = _usbPipes[nEvent]._pCurPacket;
			}

			_usbPipes[nEvent].iTotalQueue += _usbPipes[nEvent]._pCurPacket->nSize;

			SVSUTIL_ASSERT (_usbPipes[nEvent]._pLastPacket->pNext == NULL);
			_usbPipes[nEvent]._pCurPacket = NULL;

			if (CompletePacket (nEvent))
				SetEvent(gheventPackets);
		}

		SVSUTIL_ASSERT(_usbPipes[nEvent]._hTransfer);
		(*_lpUsbFuncs->lpCloseTransfer)(_usbPipes[nEvent]._hTransfer);
		_usbPipes[nEvent]._hTransfer = NULL;

		BOOL bSubmit = SubmitReadRequest(nEvent);

		gpsynchUsbDevice->Unlock();
		
		if (!bSubmit)
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] reader thread : Could not resubmit the request. Closing down\n"));
			fStop = TRUE;
			break;
		}
	}

	if (fStop)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] reader thread : closing down\n"));
		SetEvent (gheventClose);
		CloseConnectionHelper();
	}

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] reader thread : exited\n"));
	return FALSE;
}

BOOL CUsbDevice::SubmitReadRequest(int nEvent)
{
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] SubmitReadRequest %s\n", nEvent == EVENT_BULK ? L"ACL" : (nEvent == EVENT_INTERRUPT ? L"Event" : (nEvent == EVENT_ISOCH ? L"SCO" : L"Error"))));

	SVSUTIL_ASSERT(gpsynchUsbDevice->IsLocked());

	if ( (nEvent == EVENT_ISOCH) && !IsScoActive() ) {
		IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] -SubmitReadRequest :: SCO read when no ISOCH endpoint found\n"));
		return FALSE;
	}

	ResetEvent(gheventRead[nEvent]);
	
	SVSUTIL_ASSERT(!_usbPipes[nEvent]._hTransfer);
	SVSUTIL_ASSERT(_lpUsbFuncs != NULL);

	if (! _usbPipes[nEvent]._pCurPacket)
		_usbPipes[nEvent]._pCurPacket = new PACKET;

	if (! _usbPipes[nEvent]._pCurPacket)
	{
		IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] -SubmitReadRequest :: out of memory!\n"));
		return FALSE;
	}

	BOOL bHalted = FALSE;
	if ((*_lpUsbFuncs->lpIsPipeHalted)(_usbPipes[nEvent]._hPipe, &bHalted) && bHalted)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] SubmitReadRequest : Pipe halted -- resetting!\n"));
		(*_lpUsbFuncs->lpResetPipe)(_usbPipes[nEvent]._hPipe);
	}

	unsigned int i;

	switch(nEvent)
	{
	case EVENT_BULK:
		_usbPipes[nEvent]._hTransfer = (*_lpUsbFuncs->lpIssueBulkTransfer)(_usbPipes[nEvent]._hPipe, ReadNotify, (void *)nEvent, 
								USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_NO_WAIT, 
								_uiPacketSize, _usbPipes[nEvent]._pCurPacket->data, NULL);
		break;
	case EVENT_INTERRUPT:
		_usbPipes[nEvent]._hTransfer = (*_lpUsbFuncs->lpIssueInterruptTransfer)(_usbPipes[nEvent]._hPipe, ReadNotify, (void *)nEvent, 
								USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_SEND_TO_ENDPOINT | USB_NO_WAIT,
								_endpEvents.wMaxPacketSize, _usbPipes[nEvent]._pCurPacket->data, NULL);
		break;
	case EVENT_ISOCH:
		for (i = 0; i < _uiSCOReadFrames; i++)
		{
			_dwInTransferLens[i] = _endpSCOIn[_nScoPipeIdx].wMaxPacketSize;
		}
		_usbPipes[nEvent]._hTransfer = (*_lpUsbFuncs->lpIssueIsochTransfer)(_usbPipes[nEvent]._hPipe, ReadNotify, (void *)nEvent, 
								USB_IN_TRANSFER | USB_NO_WAIT | USB_START_ISOCH_ASAP,
								0, _uiSCOReadFrames, _dwInTransferLens, _usbPipes[nEvent]._pCurPacket->data, NULL);
		break;
	default:
		SVSUTIL_ASSERT(FALSE);
		break;
	}

	if (_usbPipes[nEvent]._hTransfer == NULL)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to issue transfer on pipe %d. GetLastError() returns 0x%08x\n", nEvent, GetLastError()));
		return FALSE;
	}

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -SubmitReadRequest %s : TRUE\n", nEvent == EVENT_BULK ? L"ACL" : (nEvent == EVENT_INTERRUPT ? L"Event" : (nEvent == EVENT_ISOCH ? L"SCO" : L"Error"))));

	return TRUE;
}

DWORD CALLBACK CUsbDevice::ReadNotify(LPVOID lpvNotifyParameter)
{
	int nEvent = (int )lpvNotifyParameter;

	IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] ReadRequest arrived for %s\n", nEvent == EVENT_BULK ? L"ACL" : (nEvent == EVENT_INTERRUPT ? L"Event" : (nEvent == EVENT_ISOCH ? L"SCO" : L"Error"))));

	SVSUTIL_ASSERT(nEvent >=0 && nEvent < NUM_IN_PIPES);

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] Calling SetEvent() on event %d\n", nEvent));
	SetEvent(gheventRead[nEvent]);

	return 0;
}

DWORD CALLBACK CUsbDevice::WriteNotify(LPVOID lpvNotifyParameter)
{
	int dwCookie = (DWORD)lpvNotifyParameter;

	IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] Write completed async with cookie %d\n", dwCookie));

	gpRingBuffer->SignalComplete (dwCookie);	
	
	return 0;
}

⌨️ 快捷键说明

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