📄 hci.cxx
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
//
// Bluetooth HCI layer
//
//
// Module Name:
//
// hci.cxx
//
// Abstract:
//
// This file implements Bluetooth HCI layer
//
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <svsutil.hxx>
#include <bt_debug.h>
#include <bt_os.h>
#include <bt_buffer.h>
#include <bt_hcip.h>
#include <bt_ddi.h>
static void ConnectTransport (void);
static void ShutdownTransport (void);
int hci_disconnect_transport (int fFinalShutdown);
BD_BUFFER *AllocBuffer (int size);
BD_BUFFER *CopyBuffer (BD_BUFFER *pSource);
BD_BUFFER *FreeBuffer (BD_BUFFER *pBuffer);
#define HCI_BUFFER (256 + 3)
#define HCI_MEM_SCALE 10
#define HCI_TIMER_SCALE 20000
#define DEFAULT_WORKER_THREAD_PRIORITY 132
struct HCI_CONTEXT : public SVSAllocClass {
HCI_CONTEXT *pNext;
HCI_EVENT_INDICATION ei;
HCI_CALLBACKS c;
unsigned int uiControl;
BD_ADDR ba;
unsigned int class_of_device;
unsigned char link_type;
void *pUserContext;
HCI_CONTEXT (void) {
memset (this, 0, sizeof(*this));
}
};
struct BasebandConnection {
BasebandConnection *pNext;
unsigned short connection_handle;
BD_ADDR ba;
unsigned int remote_cod;
unsigned char link_type;
unsigned int fEncrypted : 1;
unsigned int fAuthenticated : 1;
unsigned int fMode : 3;
HCI_CONTEXT *pOwner;
int cAclDataPacketsPending;
int cScoDataPacketsPending;
BD_BUFFER *pAclPacket;
int cAclBytesComplete;
DWORD dwNextScoSyncTime;
DWORD dwScoPendingPacketCount;
~BasebandConnection (void) {
if (pAclPacket && pAclPacket->pFree)
pAclPacket->pFree (pAclPacket);
}
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
struct HCIPacket {
HCIPacket *pNext;
HCI_TYPE ePacketType;
union {
struct {
unsigned short hConnection;
int cTotal;
int cSubsPending;
int cCompleted;
} DataPacketAcl;
struct {
unsigned short hConnection;
int cTotal;
int cSubsPending;
} DataPacketSco;
struct {
unsigned short hConnection;
int cTotal;
int cSubsPending;
} DataPacketU;
struct {
unsigned short opCode;
HCI_EVENT_CODE eEvent;
PacketMarker m;
int iEventRef;
} CommandPacket;
} uPacket;
HCI_CONTEXT *pOwner;
void *pCallContext;
BD_BUFFER *pContents;
HCIPacket (HCI_TYPE a_eType, HCI_CONTEXT *a_pOwner, void *a_pCallContext, unsigned int a_cSize) {
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"PACKET TRACK :: Created packet 0x%08x\n", this));
memset (this, 0, sizeof(*this));
ePacketType = a_eType;
pOwner = a_pOwner;
pCallContext = a_pCallContext;
uPacket.CommandPacket.m.fMarker = BTH_MARKER_NONE;
if (a_cSize)
pContents = BufferAlloc (a_cSize);
else
pContents = NULL;
}
HCIPacket (HCI_TYPE a_eType, HCI_CONTEXT *a_pOwner, void *a_pCallContext, unsigned int a_cSize, BD_ADDR *pba) {
SVSUTIL_ASSERT (a_eType == COMMAND_PACKET);
HCIPacket::HCIPacket (a_eType, a_pOwner, a_pCallContext, a_cSize);
uPacket.CommandPacket.m.fMarker = BTH_MARKER_ADDRESS;
uPacket.CommandPacket.m.ba = *pba;
}
HCIPacket (HCI_TYPE a_eType, HCI_CONTEXT *a_pOwner, void *a_pCallContext, unsigned int a_cSize, unsigned short connection_handle) {
SVSUTIL_ASSERT (a_eType == COMMAND_PACKET);
HCIPacket::HCIPacket (a_eType, a_pOwner, a_pCallContext, a_cSize);
uPacket.CommandPacket.m.fMarker = BTH_MARKER_CONNECTION;
uPacket.CommandPacket.m.connection_handle = connection_handle;
}
~HCIPacket (void) {
IFDBG(DebugOut (DEBUG_HCI_PACKETS, L"PACKET TRACK :: Destroyed packet 0x%08x\n", this));
if (pContents)
pContents->pFree (pContents);
}
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
enum HCI_LIFE_STAGE {
JustCreated = 0,
Initializing,
AlmostRunning,
Connected,
Disconnected,
ShuttingDown,
Error
};
struct InquiryResultList {
InquiryResultList *pNext;
InquiryResultBuffer irb;
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
struct ConnReqData {
ConnReqData *pNext;
BD_ADDR ba;
unsigned int cod;
void *operator new (size_t iSize);
void operator delete(void *ptr);
};
int RetireCall (HCIPacket *pPacket, HCI_CONTEXT *pDeviceContext, void *pCallContext, int iError);
struct HCI : public SVSSynch {
HCI_LIFE_STAGE eStage;
FixedMemDescr *pfmdPackets;
FixedMemDescr *pfmdConnections;
FixedMemDescr *pfmdInquiryResults;
FixedMemDescr *pfmdConnReqData;
HCIPacket *pPackets;
HCIPacket *pPacketsSent;
HCIPacket *pPacketsPending;
BasebandConnection *pConnections;
HCI_CONTEXT *pContexts;
HCI_CONTEXT *pPeriodicInquiryOwner;
InquiryResultList *pInquiryResults;
ConnReqData *pConnReqData;
HANDLE hQueue;
HANDLE hWriterThread;
HANDLE hReaderThread;
int iCallRefCount;
int cCommandPacketsAllowed;
DWORD dwCommandPacketTimeout;
int cTotalAclDataPacketsPending; // Total num of ACL packets pending on all connections
int cTotalScoDataPacketsPending; // Total num of SCO packets pending on all connections
int fHostFlow : 1;
int fLoopback : 1;
int fUnderTest : 1;
int fScoFlow : 1;
HCI_Buffer_Size sHostBuffer;
HCI_Buffer_Size sDeviceBuffer;
unsigned __int64 llEventMask;
int iHardwareErrors;
int iReportedErrors;
HCI_PARAMETERS transport;
HANDLE hInitEvent;
void ReInit (void) {
eStage = JustCreated;
pfmdPackets = NULL;
pfmdConnections = NULL;
pfmdInquiryResults = NULL;
pPackets = NULL;
pPacketsSent = NULL;
pPacketsPending = NULL;
pConnections = NULL;
pContexts = NULL;
pPeriodicInquiryOwner = NULL;
pInquiryResults = NULL;
pConnReqData = NULL;
hQueue = NULL;
hWriterThread = hReaderThread = NULL;
iCallRefCount = 0;
cCommandPacketsAllowed = 1;
dwCommandPacketTimeout = 0;
memset (&sDeviceBuffer, 0, sizeof(sDeviceBuffer));
memset (&sHostBuffer, 0, sizeof(sHostBuffer));
memset (&transport, 0, sizeof(transport));
fHostFlow = FALSE;
fLoopback = FALSE;
fUnderTest = FALSE;
fScoFlow = FALSE;
llEventMask = 0;
iHardwareErrors = 0;
iReportedErrors = 0;
cTotalAclDataPacketsPending = 0;
cTotalScoDataPacketsPending = 0;
hInitEvent = NULL;
}
HCI (void) {
ReInit();
}
void AddRef (void) {
++iCallRefCount;
}
void Release (void) {
--iCallRefCount;
SVSUTIL_ASSERT (iCallRefCount >= 0);
}
int InCall (void) {
return iCallRefCount;
}
int IsStackRunning (void) {
return (eStage == AlmostRunning) || (eStage == Connected) || (eStage == Disconnected) || (eStage == Error);
}
void Reset (void) {
memset (&sHostBuffer, 0, sizeof(sHostBuffer));
fHostFlow = FALSE;
fLoopback = FALSE;
fUnderTest = FALSE;
fScoFlow = FALSE;
llEventMask = 0;
iHardwareErrors = 0;
iReportedErrors = 0;
while (pConnections) {
BasebandConnection *pNext = pConnections->pNext;
delete pConnections;
pConnections = pNext;
}
while (pInquiryResults) {
InquiryResultList *pNext = pInquiryResults->pNext;
delete pInquiryResults;
pInquiryResults = pNext;
}
while (pConnReqData) {
ConnReqData *pNext = pConnReqData->pNext;
delete pConnReqData;
pConnReqData = pNext;
}
pPeriodicInquiryOwner = NULL;
HCIPacket *pX = pPacketsPending;
pPacketsPending = NULL;
while (pX && (eStage == IsStackRunning ())) {
HCIPacket *pNext = pX->pNext;
RetireCall (pX, pX->pOwner, pX->pCallContext, ERROR_BUS_RESET);
pX = pNext;
}
pX = pPacketsSent;
pPacketsSent = NULL;
while (pX && (eStage == IsStackRunning ())) {
HCIPacket *pNext = pX->pNext;
RetireCall (pX, pX->pOwner, pX->pCallContext, ERROR_BUS_RESET);
pX = pNext;
}
}
};
static HCI *gpHCI = NULL;
struct InternalCommand {
HANDLE hEvent;
int fCompleted;
unsigned char status;
};
static void IncrHWErr (void) {
IFDBG(DebugOut (DEBUG_WARN, L"[HCI] IncrHWErr : to %d\n", gpHCI->iHardwareErrors + 1));
if ((++gpHCI->iHardwareErrors) > HCI_MAX_ERR) {
IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] Shutting closed because of hardware errors (%d total)\n",
gpHCI->iHardwareErrors));
ShutdownTransport ();
}
}
static int InitTrackReset (void *pCallContext, unsigned char status) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"InitTrackReset:: status %02x\n", status));
InternalCommand *pArgs = (InternalCommand *)pCallContext;
pArgs->status = status;
pArgs->fCompleted = TRUE;
SetEvent (pArgs->hEvent);
return TRUE;
}
static int InitTrackReadBufferSize (void *pCallContext, unsigned char status,
unsigned short hci_acl_data_packet_length,
unsigned char hci_sco_data_packet_length,
unsigned short hci_total_num_acl_data_packet,
unsigned short hci_total_num_sco_data_packets) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"InitTrackBufferRead:: status %02x acl len: %d packets %d sco len %d packets %d\n",
status, hci_acl_data_packet_length, hci_total_num_acl_data_packet, hci_sco_data_packet_length,
hci_total_num_sco_data_packets));
if (status == 0) {
SVSUTIL_ASSERT (gpHCI->sDeviceBuffer.ACL_Data_Packet_Length == hci_acl_data_packet_length);
SVSUTIL_ASSERT (gpHCI->sDeviceBuffer.SCO_Data_Packet_Length == hci_sco_data_packet_length);
SVSUTIL_ASSERT (gpHCI->sDeviceBuffer.Total_Num_ACL_Data_Packets == hci_total_num_acl_data_packet);
SVSUTIL_ASSERT (gpHCI->sDeviceBuffer.Total_Num_SCO_Data_Packets == hci_total_num_sco_data_packets);
}
InternalCommand *pArgs = (InternalCommand *)pCallContext;
pArgs->status = status;
pArgs->fCompleted = TRUE;
SetEvent (pArgs->hEvent);
return TRUE;
}
static int InitTrackReadLSP (void *pCallContext, unsigned char status, unsigned char features_mask[8]) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"InitTrackReadLSP:: status %02x\n", status));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -