📄 usbdev.cpp
字号:
//
// 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 + -