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

📄 usbdev.cpp

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		if ((RegQueryValueEx (hk, L"IsochAltSetting", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)))
		{
			// a setting of zero means don't open any ISOCH pipe
			if (dwData <= SCO_MAX_ALT_SETTING)
				_dwSuggestedScoAltSetting = dwData;
		}

		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"PacketSize", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			_uiPacketSize = dwData;

		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"BlockSize", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			_uiBlockSize = dwData;

		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"Priority256", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			g_USBReadThreadPriority = dwData;

		dwSize = sizeof(dwData);
		if ((RegQueryValueEx (hk, L"SCOReadPacketsPerTransfer", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
			uiSCOReadPackets = dwData;

		RegCloseKey (hk);
	}

	_uiSCOReadFrames = uiSCOReadPackets * SCO_READ_FRAMES_PER_PACKET;
	if (_uiSCOReadFrames > MAX_SCO_READ_FRAMES_PER_TRANSFER) {
		_uiSCOReadFrames = MAX_SCO_READ_FRAMES_PER_TRANSFER;
	}

	if (_dwSuggestedScoAltSetting != 0)
	{
		for (int i = 0 ; i < _nSCOInCount ; ++i)
		{
			// _dwSuggestedScoAltSetting being zero means don't open any ISOCH pipe
			if ((_endpSCOAltSetting[i] == _dwSuggestedScoAltSetting))
			{
				_nScoPipeIdx = i;

				// we only do the _uiMinPacketSize check on the SCO pipe that we will open.
				if (((DWORD)_endpSCOIn[i].wMaxPacketSize * _uiSCOReadFrames) > _uiMinPacketSize)
					_uiMinPacketSize = _endpSCOIn[i].wMaxPacketSize * _uiSCOReadFrames;
			}
		}
	}

	// sanity check -- make sure selected input endpoint has a coressponding output endpoint
	if (IsScoActive())
	{
		if ((_endpSCOOut[_nScoPipeIdx].wMaxPacketSize != _endpSCOIn[_nScoPipeIdx].wMaxPacketSize) || (_nSCOOutCount != _nSCOInCount) )
		{
			_nScoPipeIdx = -1;
			IFDBG(DebugOut (DEBUG_HCI_INIT, L"[HCI] [USB] ISOCH endpoints IN/OUT mismatch!\n"));
			SVSUTIL_ASSERT(0);
		}
	}

#if ! defined (IMMEDIATE_SETUP)
	if (_pIntfEvent && _bInitialized)
	{
		SVSUTIL_ASSERT(_pIntfEvent->Descriptor.bAlternateSetting == 0);

		USB_TRANSFER usbTrans = (*_lpUsbFuncs->lpSetInterface)(_hDevice, NULL, NULL, 0, 
					_pIntfEvent->Descriptor.bInterfaceNumber, 0);
	
		_bInitialized = (usbTrans != NULL);
	
		(*_lpUsbFuncs->lpCloseTransfer)(usbTrans);
	}
	else
	{
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : ERROR_NOT_READY (no event interface or transfer failed)\n"));
		gpsynchUsbDevice->Unlock();
		return ERROR_NOT_READY;
	}
#endif

	ResetEvent(gheventClose);
	ResetEvent(gheventWritten);

	if (_usbPipes[EVENT_INTERRUPT]._hPipe && _usbPipes[EVENT_BULK]._hPipe)		
	{
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : ERROR_SUCCESS (already initialized)\n"));
		gpsynchUsbDevice->Unlock();
		return ERROR_SUCCESS;
	}

	SVSUTIL_ASSERT(_lpUsbFuncs != NULL);

	(*_lpUsbFuncs->lpResetDefaultPipe)(_hDevice);

	BOOL fRet = FALSE;

	SVSUTIL_ASSERT(NUM_IN_PIPES == 3);
	USB_ENDPOINT_DESCRIPTOR *pendpIn[NUM_IN_PIPES] = {&_endpSCOIn[0], &_endpACLIn, &_endpEvents};

	SVSUTIL_ASSERT(NUM_OUT_PIPES == 2);
	USB_ENDPOINT_DESCRIPTOR *pendpOut[NUM_OUT_PIPES] = {&_endpSCOOut[0], &_endpACLOut}; 


	int i;
	BOOL bOpenScoPipes = FALSE;
	if (IsScoActive()) { 
		// ParseConfig() found an acceptable SCO endp

		// select the interface on which the SCO pipe can be opened
		USB_TRANSFER hTransfer;
		hTransfer = _lpUsbFuncs->lpSetInterface(_hDevice,
												NULL,
												NULL,
												0,
												SCO_INTERFACE_NUMBER,
												_endpSCOAltSetting[_nScoPipeIdx]);
		if (!hTransfer) {
			DWORD dwError = GetLastError();
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to SetInterface: intf=%d alt=%d, error %d\n", SCO_INTERFACE_NUMBER, _endpSCOAltSetting[_nScoPipeIdx], dwError));
			SetLastError(dwError);
			goto Cleanup;
		}
		_lpUsbFuncs->lpCloseTransfer(hTransfer);

		pendpIn [0] = &_endpSCOIn [_nScoPipeIdx];
		pendpOut[0] = &_endpSCOOut[_nScoPipeIdx];

		bOpenScoPipes = TRUE;
	} else {
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[HCI] [USB] SCO endpoint not found\n"));
	}

	//Open pipes for all incoming endpoints
	for (i = (bOpenScoPipes ? 0 : 1); i<NUM_IN_PIPES; i++)
	{
		_usbPipes[i]._hPipe = (*_lpUsbFuncs->lpOpenPipe)(_hDevice, pendpIn[i]);
		if (_usbPipes[i]._hPipe  == NULL)
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to open input pipe no: %d\n", i));
			goto Cleanup;
		}

		(*_lpUsbFuncs->lpResetPipe)(_usbPipes[i]._hPipe);
	}

	//Open pipes for all outgoing endpoints
	for (i = (bOpenScoPipes ? 0 : 1); i<NUM_OUT_PIPES; i++)
	{
		_hOutPipes[i] = (*_lpUsbFuncs->lpOpenPipe)(_hDevice, pendpOut[i]);
		if (_hOutPipes[i]  == NULL)
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to open output pipe no: %d\n", i));
			goto Cleanup;
		}
		(*_lpUsbFuncs->lpResetPipe)(_hOutPipes[i]);
	}

	if (_uiPacketSize < _uiMinPacketSize)
		_uiPacketSize = _uiMinPacketSize;

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] packet size %d block size %d\n", _uiPacketSize, _uiBlockSize));

	if (ERROR_SUCCESS != gpRingBuffer->Init()) {
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : Failed to initialize Ring Buffer\n"));
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		goto Cleanup;
	}

	_pfmdPackets = svsutil_AllocFixedMemDescr (offsetof(PACKET, data) + _uiPacketSize, _uiBlockSize);
	if (!_pfmdPackets)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to allocate fixed memory for packets\n"));
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		goto Cleanup;
	}

#if defined (CONNECTION_TRACKING)
	_pHandleTree = SVSNewTree();
	if (! _pHandleTree)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to allocate tree for handles\n"));
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		goto Cleanup;
	}
#endif

	// Ensure all events are reset
	for (i=0; i<NUM_IN_PIPES; i++) 
	{
		ResetEvent(gheventRead[i]);
	}

	DWORD dwThreadId;

	SVSUTIL_ASSERT(ghthrdRead == NULL);

	ghthrdRead = CreateThread(NULL, 0, ReadThreadProcStub, this, 0, &dwThreadId);
	if (!ghthrdRead)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to create read thread.\n"));
		goto Cleanup;
	}

	CeSetThreadPriority(ghthrdRead, g_USBReadThreadPriority);

	for (i = (bOpenScoPipes ? EVENT_ISOCH : EVENT_BULK); i <= EVENT_INTERRUPT; i++) 	
	{
		if (!SubmitReadRequest(i))
		{
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] ReadRequest to %d failed.\n", i));
			goto Cleanup;
		}
	}

	if (bOpenScoPipes) {
		_bCloseScoIO = FALSE;
	}

#if defined (BT_USE_CELOG)
	if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"software\\microsoft\\bluetooth\\debug", 0, KEY_READ, &hk)) {
		DWORD dwType;
		DWORD dw;
		DWORD dwSize = sizeof(dw);

		if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"celog", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
			(dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
			g_fCeLog = IsCeLogStatus (CELOGSTATUS_ENABLED_GENERAL);

		RegCloseKey (hk);
	}

	if (g_fCeLog) {
		BTH_CELOG_START_DATA sd;

		sd.eTransport = USB;
		GetLocalTime (&sd.st);
		wsprintf (sd.szDriverString, L"USB Driver v. 0x%08x SCO Active: %d", HCI_INTERFACE_VERSION_1_1, IsScoActive ());

		CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &sd, sizeof(sd), 0, CELZONE_ALWAYSON, CELOG_FLAG_START);
	}
#endif

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : ERROR_SUCCESS\n"));
	gpsynchUsbDevice->Unlock();

	return ERROR_SUCCESS;

Cleanup:
	DWORD dwErr = GetLastError();
	gpsynchUsbDevice->Unlock();
	CloseConnection();

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : %d\n", dwErr));

	return dwErr;
}

BOOL CUsbDevice::CloseConnectionHelper()
{
	gpsynchUsbDevice->Lock();

	if (!_bInitialized)
	{
		gpsynchUsbDevice->Unlock();
		return FALSE;
	}

	_bCloseScoIO = TRUE;
	
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[HCI] Calling SetEvent(gheventClose)\n"));
	SetEvent(gheventClose);

	SVSUTIL_ASSERT(_lpUsbFuncs != NULL);


	for (int i=0; i<NUM_IN_PIPES; i++)
	{
		if (_usbPipes[i]._hTransfer)
		{
			if (!_lpUsbFuncs->lpIsTransferComplete(_usbPipes[i]._hTransfer)) {
				_lpUsbFuncs->lpAbortTransfer(_usbPipes[i]._hTransfer, 0);
			}

			(*_lpUsbFuncs->lpCloseTransfer)(_usbPipes[i]._hTransfer);
			_usbPipes[i]._hTransfer = NULL;
		}

		if (_usbPipes[i]._hPipe)
		{
			(*_lpUsbFuncs->lpClosePipe)(_usbPipes[i]._hPipe);
			_usbPipes[i]._hPipe = NULL;
		}

		_usbPipes[i].CUsbPipe::CUsbPipe ();
	}

	for (i=0; i<NUM_OUT_PIPES; i++)
	{
		if (_hOutPipes[i])
		{
			(*_lpUsbFuncs->lpClosePipe)(_hOutPipes[i]);
			_hOutPipes[i] = NULL;
		}
	}

	if (_pfmdPackets)
	{
		svsutil_ReleaseFixedNonEmpty(_pfmdPackets); 
		_pfmdPackets = NULL;
	}

	gpRingBuffer->Deinit();

#if defined (CONNECTION_TRACKING)
	if (_pHandleTree)
	{
		delete _pHandleTree;
		_pHandleTree = NULL;
	}
#endif

#if defined (NATIVE_SEQUENCING)
	while (_pPacketList)
	{
		CompletedPacket *pNext = _pPacketList->pNext;
		free (_pPacketList);
		_pPacketList = pNext;
	}

	_pLastPacket = NULL;
#endif

	_nScoPipeIdx = -1;

	gpsynchUsbDevice->Unlock();
	
	return TRUE;
}

void CUsbDevice::CloseConnection(void)
{
	SVSUTIL_ASSERT(!gpsynchUsbDevice->IsLocked());

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] +CloseConnection\n"));
	if (!CloseConnectionHelper())
	{
		IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] -CloseConnection - device not active\n"));
		return;
	}

	gpsynchUsbDevice->Lock();

	HANDLE hThread = NULL;
	if (ghthrdRead)
	{
		hThread = ghthrdRead;
		ghthrdRead = NULL;
	}

	gpsynchUsbDevice->Unlock();

	ASSERT(!gpsynchUsbDevice->IsLocked());	//make sure the lock is released before waiting for the thread to die

	if (hThread)
	{
		WaitForSingleObject(hThread, INFINITE);
		CloseHandle(hThread);
	}

#if defined (BT_USE_CELOG)
	if (g_fCeLog) {
		BTH_CELOG_STOP_DATA sd;
		GetLocalTime (&sd.st);

		CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &sd, sizeof(sd), 0, CELZONE_ALWAYSON, CELOG_FLAG_STOP);

		g_fCeLog = FALSE;
	}
#endif

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -CloseConnection\n"));
}

int CUsbDevice::WritePacket (unsigned char *pBuffer, int nLen, HCI_TYPE eType) 
{
	gpsynchUsbDevice->Lock ();

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] WritePacket : %s : %d bytes\n", eType == COMMAND_PACKET ? L"COMMAND" : (eType == DATA_PACKET_ACL ? L"ACL" : (eType == DATA_PACKET_SCO ? L"SCO" : L"Error")), nLen));

	if (!CheckDevice()) 
	{
		gpsynchUsbDevice->Unlock ();
		return FALSE;
	}

	if ((DATA_PACKET_SCO == eType) && !IsScoActive()) {
		// HCI wants to send a SCO packet, but an ISOCH endpoint was not found and opened.
		// HCI should be smart enough to know that SCO is not supported on this device
		// because bthusb could not find an ISOCH endpoint.
		// HCI can figure this out from HCI_PARAMETERS struct.
		gpsynchUsbDevice->Unlock ();
		return FALSE;
	}

	SVSUTIL_ASSERT(pBuffer);
	SVSUTIL_ASSERT(nLen > 0);

	SVSUTIL_ASSERT(_lpUsbFuncs != NULL);

	switch (eType) 
	{
		case COMMAND_PACKET:
		{
			USB_DEVICE_REQUEST usbDevReq;
			usbDevReq.bmRequestType = USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_CLASS;	
			usbDevReq.bRequest = 0;
			usbDevReq.wValue = 0;
			usbDevReq.wIndex = 0;

⌨️ 快捷键说明

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