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

📄 usbdev.cpp

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

			USB_HANDLE h = _hDevice;
			LPISSUE_VENDOR_TRANSFER f = _lpUsbFuncs->lpIssueVendorTransfer;
			gpsynchUsbDevice->Unlock ();

			USB_TRANSFER hTransfer = f (h, NULL, NULL, USB_OUT_TRANSFER, &usbDevReq, pBuffer, NULL);

#if defined (BT_USE_CELOG)
			if (g_fCeLog) {
				CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, (unsigned short)nLen, 0, CELZONE_ALWAYSON, CELOG_FLAG_HCI_COMMAND_OUT);
			}
#endif

			gpsynchUsbDevice->Lock ();

			if (! hTransfer) {
				IFDBG(DebugOut(DEBUG_ERROR, L"[USB] -WritePacket : (COMMAND_PACKET) TRANSFER FAILED!\n"));
				
				gpsynchUsbDevice->Unlock ();
				return FALSE;
			}
			
			(*gpUsbDevice->_lpUsbFuncs->lpCloseTransfer)(hTransfer);

			break;
		}

		case DATA_PACKET_ACL:
		{
			SVSUTIL_ASSERT(_hOutPipes[PACKET_ACL]);

			USB_PIPE h = _hOutPipes[PACKET_ACL];
			LPISSUE_BULK_TRANSFER f = _lpUsbFuncs->lpIssueBulkTransfer;
			

			DWORD dwCookie = 0xffffffff;
			int nAlignLen = nLen + (4 - (nLen & 3));
			USBWritePacket* pPacket = gpRingBuffer->GetWritePacket(nAlignLen, &dwCookie);

			if (! pPacket) {
				gpsynchUsbDevice->Unlock ();
				USB_TRANSFER hTransfer = f (h, NULL, NULL, USB_OUT_TRANSFER, nLen, pBuffer, NULL);
				gpsynchUsbDevice->Lock ();

				if (! hTransfer) {
					IFDBG(DebugOut(DEBUG_ERROR, L"[USB] -WritePacket : (DATA_PACKET_ACL) TRANSFER FAILED!\n"));
					
					gpsynchUsbDevice->Unlock ();
					return FALSE;
				}
				
				(*gpUsbDevice->_lpUsbFuncs->lpCloseTransfer)(hTransfer);
			}
			else {

				pPacket->eType = eType;
				memcpy(pPacket->pBuffer, pBuffer, nLen);

				UCHAR* pTmp = pPacket->pBuffer;

				gpsynchUsbDevice->Unlock ();
				USB_TRANSFER hTransfer = f (h, WriteNotify, (LPVOID)dwCookie, USB_OUT_TRANSFER | USB_NO_WAIT, nLen, pTmp, NULL);
				gpsynchUsbDevice->Lock ();

				if (! hTransfer) {
					IFDBG(DebugOut(DEBUG_ERROR, L"[USB] -WritePacket : (DATA_PACKET_ACL) TRANSFER FAILED!\n"));

					gpRingBuffer->CompletePacket(dwCookie, NULL);

					gpsynchUsbDevice->Unlock ();
					return FALSE;
				}

				// If transfer is already complete, close it.  Otherwise, copy handle and close async.
				if ((*gpUsbDevice->_lpUsbFuncs->lpIsTransferComplete)(hTransfer)) {
					(*gpUsbDevice->_lpUsbFuncs->lpCloseTransfer)(hTransfer);				
				} else {
					pPacket->hTransfer = hTransfer;
				}
			}

#if defined (BT_USE_CELOG)
			if (g_fCeLog) {
				CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, (unsigned short)nLen, 0, CELZONE_ALWAYSON, CELOG_FLAG_HCI_ACL_OUT);
			}
#endif

			break;
		}

		case DATA_PACKET_SCO:
		{
			USB_PIPE hPipe = _hOutPipes[PACKET_SCO];

			SVSUTIL_ASSERT( (nLen / _endpSCOOut[_nScoPipeIdx].wMaxPacketSize) <= SCO_WRITE_FRAMES_PER_PACKET );
			if ( (nLen / _endpSCOOut[_nScoPipeIdx].wMaxPacketSize) > SCO_WRITE_FRAMES_PER_PACKET ) {
				IFDBG(DebugOut (DEBUG_ERROR, L"[USB] SCO packet len exceeds 3 frames\n"));
				break;
			}
			
			DWORD dwCookie;
			int nAlignLen = nLen + (4 - (nLen & 3));
			USBWritePacket* pPacket = gpRingBuffer->GetWritePacket(nAlignLen, &dwCookie);

			if (! pPacket) {
				DWORD dwLens[SCO_WRITE_FRAMES_PER_PACKET];
				
				for (int i = 0; i < SCO_WRITE_FRAMES_PER_PACKET; i++) {
					dwLens[i] = SCO_DEFAULT_SAMPLE_SIZE;				
					if (i < 3) {
						// First 3 packets have 1 extra byte for SCO header
						dwLens[i]++;	
					}
				}
				
				gpsynchUsbDevice->Unlock ();
				USB_TRANSFER hTransfer = _lpUsbFuncs->lpIssueIsochTransfer(
										hPipe, 
										NULL, 
										NULL, 
										USB_OUT_TRANSFER|USB_START_ISOCH_ASAP|USB_NO_WAIT, 
										0, 
										SCO_WRITE_FRAMES_PER_PACKET, 
										dwLens, 
										pBuffer, 
										NULL);
				gpsynchUsbDevice->Lock ();	

				if (! hTransfer) {
					IFDBG(DebugOut(DEBUG_ERROR, L"[USB] -WritePacket : (DATA_PACKET_SCO) TRANSFER FAILED!\n"));
					
					gpsynchUsbDevice->Unlock ();
					return TRUE; // return TRUE since we can handle this gracefully
				}
			}
			else {
				pPacket->eType = eType;
				memcpy(pPacket->pBuffer, pBuffer, nLen);

				for (int i = 0; i < SCO_WRITE_FRAMES_PER_PACKET; i++) {
					pPacket->dwLens[i] = SCO_DEFAULT_SAMPLE_SIZE;				
					if (i < 3) {
						// First 3 packets have 1 extra byte for SCO header
						pPacket->dwLens[i]++;	
					}
				}

				DWORD* pTmpLens = pPacket->dwLens;
				UCHAR* pTmpBuff = pPacket->pBuffer;

				gpsynchUsbDevice->Unlock ();
				USB_TRANSFER hTransfer = _lpUsbFuncs->lpIssueIsochTransfer(
										hPipe, 
										WriteNotify, 
										(LPVOID)dwCookie, 
										USB_OUT_TRANSFER|USB_START_ISOCH_ASAP|USB_NO_WAIT, 
										0, 
										SCO_WRITE_FRAMES_PER_PACKET, 
										pTmpLens, 
										pTmpBuff, 
										NULL);
				gpsynchUsbDevice->Lock ();

				if (! hTransfer) {
					IFDBG(DebugOut(DEBUG_ERROR, L"[USB] -WritePacket : (DATA_PACKET_SCO) TRANSFER FAILED!\n"));
				
					gpRingBuffer->CompletePacket(dwCookie, NULL);

					gpsynchUsbDevice->Unlock ();
					return TRUE; // return TRUE since we can handle this gracefully
				}

				// If transfer is already complete, close it.  Otherwise, copy handle and close async.
				if ((*gpUsbDevice->_lpUsbFuncs->lpIsTransferComplete)(hTransfer)) {
					(*gpUsbDevice->_lpUsbFuncs->lpCloseTransfer)(hTransfer);				
				} else {
					pPacket->hTransfer = hTransfer;
				}
			}
			
#if defined (BT_USE_CELOG)
			if (g_fCeLog) {
				CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, (unsigned short)nLen, 0, CELZONE_ALWAYSON, CELOG_FLAG_HCI_SCO_OUT);
			}
#endif			

			break;
		}

		default:
			IFDBG(DebugOut (DEBUG_ERROR, L"[HCI - USB] WritePacket :: Invalid code!\n"));
			break;
	}

	gpsynchUsbDevice->Unlock ();

	return TRUE;
}

int CUsbDevice::GetBuffer (int nType, int cOffset, int cNeeded, unsigned char *d, int fCleanPackets)
{
	// If we remove packets from the queue, the transfer must be for the entire packet.
	// The code below assumes it in calculation of how much data has been removed from the
	// queue.

	SVSUTIL_ASSERT ((! fCleanPackets) || (cOffset == 0));

	CUsbPipe *pPipe = &_usbPipes[nType];

	if (pPipe->_pPackets == NULL)
	{
		SVSUTIL_ASSERT (! fCleanPackets);
		return FALSE;
	}

	PACKET *pPacket = pPipe->_pPackets;

	while (pPacket)
	{
		if (pPacket->nSize - pPacket->nOffset > cOffset)
			break;

		cOffset -= pPacket->nSize - pPacket->nOffset;
		if (fCleanPackets)
		{
			pPipe->_pPackets = pPacket->pNext;
			if (! pPipe->_pPackets)
				pPipe->_pLastPacket = NULL;

			delete pPacket;
			pPacket = pPipe->_pPackets;
		}
		else
			pPacket = pPacket->pNext;
	}

	while (pPacket && cNeeded)
	{
		int cTransfer = pPacket->nSize - pPacket->nOffset - cOffset;
		if (cTransfer > cNeeded)
			cTransfer = cNeeded;

		memcpy (d, pPacket->data + pPacket->nOffset + cOffset, cTransfer);

		if (fCleanPackets)
		{
			pPipe->iTotalQueue -= cTransfer;

			pPacket->nOffset += cTransfer + cOffset;
			SVSUTIL_ASSERT (pPacket->nOffset <= pPacket->nSize);

			if (pPacket->nOffset == pPacket->nSize)
			{
				pPipe->_pPackets = pPacket->pNext;
				if (! pPipe->_pPackets)
					pPipe->_pLastPacket = NULL;

				delete pPacket;
				pPacket = pPipe->_pPackets;
			}
			else
				SVSUTIL_ASSERT (cNeeded == cTransfer);
		}
		else
			pPacket = pPacket->pNext;

		d += cTransfer;
		cNeeded -= cTransfer;
		cOffset = 0;

		SVSUTIL_ASSERT (cNeeded >= 0);
	}

	if (cNeeded != 0)
	{
		SVSUTIL_ASSERT (! fCleanPackets);
		return FALSE;
	}

	return TRUE;
}

int CUsbDevice::PacketSize (int nType)
{
	unsigned char d[2];

	CUsbPipe *pPipe = &_usbPipes[nType];

	switch (nType)
	{
	case EVENT_ISOCH:
		if (!GetBuffer(nType, 2, 1, d, FALSE))
			return 0;
		return d[0] + SCO_HEADER_SIZE;	

	case EVENT_BULK:
		if (!GetBuffer(nType, 2, 2, d, FALSE))
			return 0;
		SVSUTIL_ASSERT (pPipe->_pPackets->nSize >= 4);
		return (d[0] | (d[1] << 8)) + ACL_HEADER_SIZE;	

	case EVENT_INTERRUPT:
		if (!GetBuffer(nType, 1, 1, d, FALSE))
			return 0;
		SVSUTIL_ASSERT (pPipe->_pPackets->nSize >= 3);
		return d[0] + EVENT_HEADER_SIZE;
	}

	IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] UNKNOWN PACKET ERROR!\n"));
	SVSUTIL_ASSERT (0);

	return 0;
}

int CUsbDevice::CompletePacket (int nType) {
#if defined (NATIVE_SEQUENCING)
	int nPacketSize = PacketSize(nType);
	SVSUTIL_ASSERT ((nPacketSize == 0) || (_usbPipes[nType].iTotalQueue > 0));

	if ((nPacketSize == 0) || (_usbPipes[nType].iTotalQueue < nPacketSize))
		return FALSE;

	if ((nPacketSize <= 0) || (nPacketSize > PACKET_SIZE_R))
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Packet of invalid size.\n"));
		return FALSE;
	}

	int fRes = FALSE;

	CompletedPacket *pNewPacket = (CompletedPacket *)malloc (offsetof (CompletedPacket, ucData) + nPacketSize);
	if (pNewPacket) {
		pNewPacket->eType	= nType;
		pNewPacket->cLength = nPacketSize;
		pNewPacket->pNext	= NULL;
		fRes = GetBuffer (pNewPacket->eType, 0, pNewPacket->cLength, pNewPacket->ucData, TRUE);
		if (fRes) {
			if (_pLastPacket)
				_pLastPacket->pNext = pNewPacket;
			else
				_pPacketList = pNewPacket;
			_pLastPacket = pNewPacket;
		} else {
			SVSUTIL_ASSERT (0);
			free (pNewPacket);
		}
	} else
		SVSUTIL_ASSERT (0); //OOM

	return fRes;
#else
	return TRUE;
#endif
}

int CUsbDevice::RetrievePacket (unsigned char *pBuffer, int *pnLen, int *pnType, DWORD *pdwTimeout)
{
#if defined (NATIVE_SEQUENCING)
	if (_pPacketList) {
		*pnLen = _pPacketList->cLength;
		*pnType = _pPacketList->eType;
		memcpy (pBuffer, _pPacketList->ucData, _pPacketList->cLength);

		CompletedPacket *pNext = _pPacketList->pNext;
		free (_pPacketList);
		_pPacketList = pNext;
		if (! _pPacketList)
			_pLastPacket = NULL;

		return TRUE;
	}

	return FALSE;
#else
#if defined (CONNECTION_TRACKING)
	// If we are tracking connections, give slight bias to bulk data
	// since in processing disconnection events we need to reverse
	// priorities and process data that comes slightly after the disconnect
	// events...
	for (int i = EVENT_ISOCH ; i <= EVENT_INTERRUPT; ++i)
#else
	for (int i = EVENT_INTERRUPT ; i >= EVENT_ISOCH; --i)
#endif
	{
		int nPacketSize = PacketSize(i);
		SVSUTIL_ASSERT ((nPacketSize == 0) || (_usbPipes[i].iTotalQueue > 0));

		if ((nPacketSize == 0) || (_usbPipes[i].iTotalQueue < nPacketSize))
			continue;

		if ((nPacketSize <= 0) || (nPacketSize > PACKET_SIZE_R))
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Packet of invalid size.\n"));
			return FALSE;
		}

#if defined (CONNECTION_TRACKING)
		//	Bulk packet reads can preceed interrupts. This would be *REALLY* bad
		//	if this interrupt is a connection completion event. Therefore we
		//	will stall data packets for 1/2 sec unless connection event has been
		//	received.

		if (i == EVENT_BULK) {
			unsigned char d[2];
			if (GetBuffer (i, 0, 2, d, FALSE) &&
				((GetTickCount () - _usbPipes[i]._pPackets->dwWhenReceived) <
				(CONNECTION_TRACKING_TIMEOUT / 2))) {
				unsigned short hConn = d[0] | ((d[1] & 0xf) << 8);
				if (! _pHandleTree->Locate (hConn)) {
					IFDBG(DebugOut (DEBUG_WARN, L"USB TRANSPORT: ****PACKET STALLED %d ms****\n", CONNECTION_TRACKING_TIMEOUT));
					*pdwTimeout = CONNECTION_TRACKING_TIMEOUT;

					continue;
				}
			}
		}
#endif

		*pnType = i;
		*pnLen= nPacketSize;

⌨️ 快捷键说明

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