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

📄 usbdev.cpp

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  

	usbdev.cpp

Abstract:  

	Bluetooth HCI USB interface
	
Functions:


Notes:

--*/
#if ! defined (SDK_BUILD)
#define BT_USE_CELOG		1
#endif

#include <windows.h>
#include <windev.h>
#include <usbdi.h>
#include <svsutil.hxx>

#include <bt_buffer.h>
#include <bt_hcip.h>
#include <bt_os.h>
#include <bt_debug.h>

#include <bt_tdbg.h>
#include "usbdev.h"

// constants used for selecting the SCO pipe
#define SCO_INTERFACE_NUMBER			1
#define SCO_DEFAULT_ALT_SETTING 		0 // by default, SCO is off
#define SCO_MAX_ALT_SETTING 			5


/////////////////////////////////////////////////////////////////////
// #define, structs, global vars, for SCO writing system.

#define DEFAULT_USB_READ_THREAD_PRIORITY       131

//
// global variables
//
static int 				g_USBReadThreadPriority; // Read Thread priority

CRingBuffer				*gpRingBuffer;

CSynch					*gpsynchUsbDevice;
CUsbDevice				*gpUsbDevice = NULL;

HANDLE					gheventRead[NUM_IN_PIPES];
HANDLE					gheventClose;
HANDLE					gheventWritten;
HANDLE					gheventPackets;
HANDLE					ghthrdRead = NULL;

static BOOL 			gfStopHardware = FALSE;

static int	g_fCeLog = FALSE;


CUsbDevice::CUsbDevice()
{
	memset (this, 0, sizeof(*this));
}

CUsbDevice::~CUsbDevice()
{

}

BOOL CUsbDevice::DeviceAttach(USB_HANDLE hDevice, LPCUSB_FUNCS lpUsbFuncs)
{
	CLocalCriticalSection lcs(gpsynchUsbDevice);
	
	if (_bInitialized)	
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] ERROR: Second device detected. Only one bluetooth device is supported.\n"));
		return FALSE;
	}

	if (_bClosing)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] ERROR: Currently closing. Cannot reattach.\n"));
		return FALSE;
	}

	SVSUTIL_ASSERT(_hDevice == NULL);
	SVSUTIL_ASSERT(_lpUsbFuncs == NULL);

	_hDevice = hDevice;
	_lpUsbFuncs = lpUsbFuncs;

	if (!Initialize())
		return FALSE;

	if (gCallback && !gfStopHardware)
		gCallback (DEVICE_UP, NULL); 

	return TRUE;
}

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

	if ((! _bInitialized) || _bClosing)
	{
		gpsynchUsbDevice->Unlock();
		return TRUE;
	}

	SVSUTIL_ASSERT(_bInitialized);
	SVSUTIL_ASSERT(!_bClosing);

	_bClosing = TRUE;

	gpsynchUsbDevice->Unlock();

	CloseConnection();

	gpsynchUsbDevice->Lock();


	_bInitialized = FALSE;
	_bClosing = FALSE;

	SVSUTIL_ASSERT(_hDevice);
	SVSUTIL_ASSERT(_lpUsbFuncs != NULL);

	_hDevice = NULL;
	_lpUsbFuncs = NULL;

	if (gCallback && !gfStopHardware)
		gCallback (DEVICE_DOWN, NULL);

	gpsynchUsbDevice->Unlock();

	return TRUE;
}

BOOL CUsbDevice::StartHardware()
{
	CLocalCriticalSection lcs(gpsynchUsbDevice);
	gfStopHardware = FALSE;
	return _bInitialized;
}

BOOL CUsbDevice::StopHardware()
{
//	CloseConnection (); 	//#error is this enough???
	gfStopHardware = TRUE;
	return TRUE;
}


BOOL CUsbDevice::CheckDevice()
{
	SVSUTIL_ASSERT(gpsynchUsbDevice->IsLocked());

	if (!_bInitialized)
	{
		IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] CheckDevice - device not active\n"));
		return FALSE;
	}
	
	if (_bClosing)
	{
		IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] CheckDevice - device closing...\n"));
		return FALSE;
	}

	return TRUE;
}


BOOL CUsbDevice::ParseConfig(LPCUSB_CONFIGURATION lpConfig)
{
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] ParseConfig : %d interfaces\n", lpConfig->dwNumInterfaces));

	if (!lpConfig)
	{
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] -ParseConfig\n"));
		return FALSE;
	}

	SVSUTIL_ASSERT(lpConfig->lpInterfaces);
	
	memset(&_endpEvents, 0, sizeof(USB_ENDPOINT_DESCRIPTOR));
	memset(&_endpACLIn, 0, sizeof(USB_ENDPOINT_DESCRIPTOR));
	memset(&_endpACLOut, 0, sizeof(USB_ENDPOINT_DESCRIPTOR));

	memset (_endpSCOIn, 0, sizeof(_endpSCOIn));
	memset (_endpSCOOut, 0, sizeof(_endpSCOOut));
	memset (_endpSCOAltSetting, 0, sizeof(_endpSCOAltSetting));

	_nSCOInCount = _nSCOOutCount = 0;
	_nScoPipeIdx = -1;

	_pIntfEvent = NULL;

	_uiMinPacketSize = 0;

	for(int i=0; i < (int)lpConfig->dwNumInterfaces; i++)
	{
		LPCUSB_INTERFACE pInterface = &lpConfig->lpInterfaces[i];

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] ParseConfig : interface %d type 0x%02x intf # %d alt 0x%02x epts %d class 0x%02x subclass 0x%02x protocol 0x%02x iInterface %d\n",
				i, pInterface->Descriptor.bDescriptorType, pInterface->Descriptor.bInterfaceNumber, pInterface->Descriptor.bAlternateSetting,
				pInterface->Descriptor.bNumEndpoints, pInterface->Descriptor.bInterfaceClass, pInterface->Descriptor.bInterfaceSubClass,
				pInterface->Descriptor.bInterfaceProtocol, pInterface->Descriptor.iInterface));

		for (int j=0; j<pInterface->Descriptor.bNumEndpoints; j++)
		{
			LPCUSB_ENDPOINT pEndpoint = &pInterface->lpEndpoints[j];

			SVSUTIL_ASSERT(pEndpoint->Descriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);

			IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] Endpoint %d : type 0x%02x address %d attr 0x%02x maxpacket %d interval %d\n", j, pEndpoint->Descriptor.bDescriptorType,
						pEndpoint->Descriptor.bEndpointAddress, pEndpoint->Descriptor.bmAttributes, pEndpoint->Descriptor.wMaxPacketSize, pEndpoint->Descriptor.bInterval));

			switch(pEndpoint->Descriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK)
			{
			case USB_ENDPOINT_TYPE_CONTROL:
				IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] Default endpoint found in interface!\n"));
				SVSUTIL_ASSERT(FALSE);	//this is the default Endpoint-0. Shouldnt be a part of any interface.
				break;

			case USB_ENDPOINT_TYPE_ISOCHRONOUS:
				IFDBG(DebugOut (DEBUG_HCI_INIT, L"[HCI] [USB] Found SCO endpoint at addr %d\n", pEndpoint->Descriptor.bEndpointAddress));


				if (USB_ENDPOINT_DIRECTION_IN(pEndpoint->Descriptor.bEndpointAddress)) {
					if (_nSCOInCount < NUM_SCO_ENDPOINTS) {
						_endpSCOIn[_nSCOInCount] = pEndpoint->Descriptor;
						_endpSCOAltSetting[_nSCOInCount] = pInterface->Descriptor.bAlternateSetting;
						SVSUTIL_ASSERT(SCO_INTERFACE_NUMBER == pInterface->Descriptor.bInterfaceNumber);

						_nSCOInCount++;
					}
				} else {
					if (_nSCOOutCount < NUM_SCO_ENDPOINTS)
						_endpSCOOut[_nSCOOutCount++] = pEndpoint->Descriptor;
				}
				break;

			case USB_ENDPOINT_TYPE_BULK:
				IFDBG(DebugOut (DEBUG_HCI_INIT, L"[HCI] [USB] Found ACL endpoint at addr %d\n", pEndpoint->Descriptor.bEndpointAddress));

				if (pEndpoint->Descriptor.wMaxPacketSize > _uiMinPacketSize)
					_uiMinPacketSize = pEndpoint->Descriptor.wMaxPacketSize;

				if (USB_ENDPOINT_DIRECTION_IN(pEndpoint->Descriptor.bEndpointAddress))
					_endpACLIn = pEndpoint->Descriptor;
				else
					_endpACLOut = pEndpoint->Descriptor;
				break;

			case USB_ENDPOINT_TYPE_INTERRUPT:
				IFDBG(DebugOut (DEBUG_HCI_INIT, L"[HCI] [USB] Found event endpoint at addr %d\n", pEndpoint->Descriptor.bEndpointAddress));

				if (pEndpoint->Descriptor.wMaxPacketSize > _uiMinPacketSize)
					_uiMinPacketSize = pEndpoint->Descriptor.wMaxPacketSize;

				SVSUTIL_ASSERT(USB_ENDPOINT_DIRECTION_IN(pEndpoint->Descriptor.bEndpointAddress));
				_endpEvents = pEndpoint->Descriptor;
				_pIntfEvent = pInterface;
				break;
			}
		}
	}

	//return TRUE if the bLength of each endpoint is valid
	int nSize = sizeof(USB_ENDPOINT_DESCRIPTOR);
	int fRet = (_endpEvents.bLength == nSize && _endpACLIn.bLength == nSize && _endpACLOut.bLength == nSize && _pIntfEvent);

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -ParseConfig : %s\n", fRet ? L"TRUE" : L"FALSE"));

	return fRet;
}

//
// _nScoPipeIdx is set to -1 if no SCO endp
// else _nScoPipeIdx is index into _endpSCOIn[], _endpSCOIntfNum[], _endpSCOAltSetting[], _endpSCOOut[]
//
// _nScoPipeIdx is set during ParseConfig()
//
BOOL CUsbDevice::IsScoActive()
{
	return (_nScoPipeIdx >= 0 && _nScoPipeIdx < NUM_SCO_ENDPOINTS);
}

BOOL CUsbDevice::Initialize()
{
	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] Initialize\n"));

	SVSUTIL_ASSERT(gpsynchUsbDevice->IsLocked());

	LPCUSB_DEVICE lpDeviceInfo = (*_lpUsbFuncs->lpGetDeviceInfo)(_hDevice);

	SVSUTIL_ASSERT(lpDeviceInfo);

	//
	// the registry tells us which SCO (ISOCH) endpoint to open
	//
	_dwSuggestedScoAltSetting = SCO_DEFAULT_ALT_SETTING;

	//Pick the active config or the first config where we find all valid endpoints
	int i=0;
	if (!ParseConfig(lpDeviceInfo->lpActiveConfig))
	{
		for (i=0; i<lpDeviceInfo->Descriptor.bNumConfigurations; i++)
			if (ParseConfig(&lpDeviceInfo->lpConfigs[i]))
				break;
	}

	if (i >= lpDeviceInfo->Descriptor.bNumConfigurations)
	{
		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -Initialize : FALSE<no configs>\n"));
		return FALSE;
	}

	SVSUTIL_ASSERT(_lpUsbFuncs != NULL);

	_bInitialized = TRUE;

#if defined (IMMEDIATE_SETUP)
	USB_DEVICE_REQUEST usbDevReq;
	usbDevReq.bmRequestType = USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE;
	usbDevReq.bRequest = USB_REQUEST_SET_CONFIGURATION;
	usbDevReq.wValue = lpDeviceInfo->lpActiveConfig->Descriptor.bConfigurationValue;
	usbDevReq.wIndex = 0;
	usbDevReq.wLength = 0;
	USB_TRANSFER usbTrans = (*_lpUsbFuncs->lpIssueVendorTransfer)(_hDevice, NULL, 
									0, USB_OUT_TRANSFER | USB_SHORT_TRANSFER_OK,
													&usbDevReq, NULL, NULL);

	if (usbTrans)
	{
		DWORD dwBytes = 0;
		DWORD dwErr = USB_CANCELED_ERROR;

		(*_lpUsbFuncs->lpGetTransferStatus)(usbTrans, &dwBytes, &dwErr);

		int fComplete = (*_lpUsbFuncs->lpIsTransferComplete)(usbTrans);
		(*_lpUsbFuncs->lpCloseTransfer)(usbTrans);

		IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] Transferred config request : %d bytes. Error : %d. Complete : %s\n", dwBytes, dwErr, fComplete ? L"yes" : L"no"));
		_bInitialized = (dwErr == USB_NO_ERROR) && fComplete;

#if defined (DEBUG) || defined (_DEBUG)
		if (! _bInitialized)
			IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] NOT INITIALIZED!!!\n"));
#endif
	}
	else
	{
		_bInitialized = FALSE;
		IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to transfer config request\n"));
	}

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

		usbTrans = (*_lpUsbFuncs->lpSetInterface)(_hDevice, NULL, NULL, 0, 
					_pIntfEvent->Descriptor.bInterfaceNumber, 0);
	
		_bInitialized = (usbTrans != NULL);
	
		(*_lpUsbFuncs->lpCloseTransfer)(usbTrans);
	}
#endif

	IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -Initialize : %s\n", _bInitialized ? L"TRUE" : L"FALSE"));

	return _bInitialized;
}

DWORD CUsbDevice::OpenConnection(void)
{
	gpsynchUsbDevice->Lock();

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

	unsigned int uiSCOReadPackets = SCO_READ_PACKETS_PER_TRANSFER;

	_uiPacketSize = DEFPACKETSIZE;
	_uiBlockSize = DEFBLOCKSIZE;

	g_USBReadThreadPriority = DEFAULT_USB_READ_THREAD_PRIORITY;
	
	HKEY hk;
	if (RegOpenKeyEx (HKEY_BASE, L"Software\\Microsoft\\Bluetooth\\hci", 0, KEY_READ, &hk) == ERROR_SUCCESS)
	{
		DWORD dwType = 0;
		DWORD dwData = 0;
		DWORD dwSize = sizeof(dwData);

⌨️ 快捷键说明

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