📄 btutils.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.
//
//------------------------------------------------------------------------------
//
// Miscellaneous Bluetooth Utilities
//
//
// Module Name:
//
// btutils.cxx
//
// Abstract:
//
// This file implements misc Bluetooth utilities
//
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <svsutil.hxx>
#include <bt_buffer.h>
#include <bt_ddi.h>
#include <bt_os.h>
#include <bt_debug.h>
int StatusToError (unsigned char status, int iGeneric) {
switch (status) {
case BT_ERROR_SUCCESS:
return ERROR_SUCCESS;
case BT_ERROR_COMMAND_DISALLOWED:
case BT_ERROR_UNKNOWN_HCI_COMMAND:
case BT_ERROR_UNSUPPORTED_FEATURE_OR_PARAMETER:
case BT_ERROR_INVALID_HCI_PARAMETER:
case BT_ERROR_UNSUPPORTED_REMOTE_FEATURE:
return ERROR_CALL_NOT_IMPLEMENTED;
case BT_ERROR_NO_CONNECTION:
return ERROR_DEVICE_NOT_CONNECTED;
case BT_ERROR_HARDWARE_FAILURE:
case BT_ERROR_UNSPECIFIED_ERROR:
return ERROR_ADAP_HDW_ERR;
case BT_ERROR_PAGE_TIMEOUT:
case BT_ERROR_CONNECTION_TIMEOUT:
case BT_ERROR_HOST_TIMEOUT:
return ERROR_TIMEOUT;
case BT_ERROR_AUTHENTICATION_FAILURE:
return ERROR_NOT_AUTHENTICATED;
case BT_ERROR_KEY_MISSING:
return ERROR_NO_USER_SESSION_KEY;
case BT_ERROR_MEMORY_FULL:
return ERROR_OUTOFMEMORY;
case BT_ERROR_MAX_NUMBER_OF_CONNECTIONS:
case BT_ERROR_MAX_NUMBER_OF_SCO_CONNECTIONS:
case BT_ERROR_MAX_NUMBER_OF_ACL_CONNECTIONS:
return ERROR_NO_SYSTEM_RESOURCES;
case BT_ERROR_HOST_REJECTED_LIMITED_RESOURCES:
case BT_ERROR_HOST_REJECTED_SECURITY_REASONS:
case BT_ERROR_HOST_REJECTED_PERSONAL_DEVICE:
case BT_ERROR_PAIRING_NOT_ALLOWED:
return ERROR_CONNECTION_REFUSED;
case BT_ERROR_OETC_USER_ENDED:
case BT_ERROR_OETC_LOW_RESOURCES:
case BT_ERROR_OETC_POWERING_OFF:
return ERROR_GRACEFUL_DISCONNECT;
case BT_ERROR_CONNECTION_TERMINATED_BY_LOCAL_HOST:
return ERROR_CONNECTION_ABORTED;
case BT_ERROR_REPEATED_ATTEMPTS:
return ERROR_CONNECTION_COUNT_LIMIT;
}
return iGeneric;
}
void BufferFree (BD_BUFFER *pBuf) {
if (! pBuf->fMustCopy)
g_funcFree (pBuf, g_pvFreeData);
}
BD_BUFFER *BufferAlloc (int cSize) {
SVSUTIL_ASSERT (cSize > 0);
BD_BUFFER *pRes = (BD_BUFFER *)g_funcAlloc (cSize + sizeof (BD_BUFFER), g_pvAllocData);
pRes->cSize = cSize;
pRes->cEnd = pRes->cSize;
pRes->cStart = 0;
pRes->fMustCopy = FALSE;
pRes->pFree = BufferFree;
pRes->pBuffer = (unsigned char *)(pRes + 1);
return pRes;
}
BD_BUFFER *BufferCopy (BD_BUFFER *pBuffer) {
BD_BUFFER *pRes = BufferAlloc (pBuffer->cSize);
pRes->cSize = pBuffer->cSize;
pRes->cStart = pBuffer->cStart;
pRes->cEnd = pBuffer->cEnd;
pRes->fMustCopy = FALSE;
pRes->pFree = BufferFree;
pRes->pBuffer = (unsigned char *)(pRes + 1);
memcpy (pRes->pBuffer, pBuffer->pBuffer, pRes->cSize);
return pRes;
}
BD_BUFFER *BufferCompress (BD_BUFFER *pBuffer) {
BD_BUFFER *pRes = BufferAlloc (BufferTotal (pBuffer));
pRes->fMustCopy = FALSE;
pRes->pFree = BufferFree;
pRes->pBuffer = (unsigned char *)(pRes + 1);
memcpy (pRes->pBuffer, pBuffer->pBuffer + pBuffer->cStart, pRes->cSize);
return pRes;
}
enum STAGES {
INITIALIZED,
STARTED,
STOPPED,
GONE
};
class UtilState : public SVSThreadPool {
public:
STAGES eStage;
UtilState (void) { eStage = INITIALIZED; }
~UtilState (void) { eStage = GONE; }
} *utilState;
SVSCookie btutil_ScheduleEvent (LPTHREAD_START_ROUTINE pfn, LPVOID lpParameter, unsigned long ulDelayTime) {
utilState->Lock ();
if (utilState->eStage != STARTED) {
utilState->Unlock ();
return 0;
}
SVSCookie res = utilState->ScheduleEvent (pfn, lpParameter, ulDelayTime);
utilState->Unlock ();
return res;
}
int btutil_UnScheduleEvent (SVSCookie ulCookie) {
utilState->Lock ();
if (utilState->eStage != STARTED) {
utilState->Unlock ();
return FALSE;
}
int res = utilState->UnScheduleEvent (ulCookie);
utilState->Unlock ();
return res;
}
#if defined (BTH_LONG_TERM_STATE)
#define MAX_LTD_BYTES 3
#define MAX_LTD_INDICES 1
#define MAX_LTD_DEVICES 16
struct LTD {
BD_ADDR ba;
int iRef;
unsigned int uiDataMask;
unsigned char ucData[MAX_LTD_BYTES];
};
struct LTD_DESCR {
int offset;
int size;
};
static CRITICAL_SECTION g_csLongTerm;
static LTD g_ltd[MAX_LTD_DEVICES];
static LTD_DESCR g_ltdDescr[MAX_LTD_INDICES] = {
{0, 3}
};
void btutil_PersistPeerInfo (BD_ADDR *pPeerBA, unsigned int fWhat, void *pData) {
if ((fWhat <= 0) || (fWhat > MAX_LTD_INDICES)) {
SVSUTIL_ASSERT (0);
return;
}
--fWhat; // convert to 0-based
int iRepl = -1;
EnterCriticalSection (&g_csLongTerm);
for (int i = 0 ; i < MAX_LTD_DEVICES ; ++i) {
if (g_ltd[i].iRef == 0)
break;
if (g_ltd[i].ba == *pPeerBA)
break;
if ((iRepl < 0) || (g_ltd[iRepl].iRef > g_ltd[i].iRef))
iRepl = i;
}
if (i < MAX_LTD_DEVICES)
iRepl = i;
g_ltd[iRepl].ba = *pPeerBA;
g_ltd[iRepl].iRef++;
g_ltd[iRepl].uiDataMask |= (1 << fWhat);
memcpy (g_ltd[iRepl].ucData + g_ltdDescr[fWhat].offset, pData, g_ltdDescr[fWhat].size);
LeaveCriticalSection (&g_csLongTerm);
}
int btutil_RetrievePeerInfo (BD_ADDR *pPeerBA, unsigned int fWhat, void *pData) {
if ((fWhat <= 0) || (fWhat > MAX_LTD_INDICES)) {
SVSUTIL_ASSERT (0);
return FALSE;
}
--fWhat; // convert to 0-based
int iRes = FALSE;
EnterCriticalSection (&g_csLongTerm);
for (int i = 0 ; i < MAX_LTD_DEVICES ; ++i) {
if (g_ltd[i].iRef == 0)
break;
if (g_ltd[i].ba == *pPeerBA) {
if (g_ltd[i].uiDataMask & (1 << fWhat)) {
memcpy (pData, g_ltd[i].ucData + g_ltdDescr[fWhat].offset, g_ltdDescr[fWhat].size);
g_ltd[i].iRef++;
iRes = TRUE;
}
break;
}
}
LeaveCriticalSection (&g_csLongTerm);
return iRes;
}
#endif
int btutil_InitializeOnce (void) {
SVSUTIL_ASSERT (utilState == NULL);
utilState = new UtilState;
#if defined (BTH_LONG_TERM_STATE)
if (utilState)
InitializeCriticalSection (&g_csLongTerm);
#endif
return utilState ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
}
int btutil_UninitializeOnce (void) {
SVSUTIL_ASSERT (utilState);
SVSUTIL_ASSERT (utilState->eStage == STOPPED);
delete utilState;
utilState = NULL;
#if defined (BTH_LONG_TERM_STATE)
DeleteCriticalSection (&g_csLongTerm);
#endif
return ERROR_SUCCESS;
}
int btutil_CreateDriverInstance (void) {
utilState->eStage = STARTED;
return ERROR_SUCCESS;
}
int btutil_CloseDriverInstance (void) {
utilState->Shutdown ();
utilState->eStage = STOPPED;
return ERROR_SUCCESS;
}
int btutil_VerifyExtendedL2CAPOptions (int cOptNum, struct btCONFIGEXTENSION **ppExtendedOptions) {
int iRes = TRUE;
__try {
for (int i = 0 ; i < cOptNum ; ++i) {
if ((ppExtendedOptions[i]->type & 0x80) == 0) {
IFDBG(DebugOut (DEBUG_WARN, L"[UTILS] btutil_VerifyExtendedL2CAPOptions :: unrecognized option 0x%02x is required - rejecting the connection!\n", ppExtendedOptions[i]->type));
iRes = FALSE;
break;
}
}
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[UTILS] btutil_VerifyExtendedL2CAPOptions :: exception in processing options!\n"));
iRes = FALSE;
}
return iRes;
}
#if defined (SDK_BUILD)
static char months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
extern "C" int CheckTime (void) {
char *pDate = __DATE__;
int iRet = FALSE;
for ( ; ; ) {
for (int i = 0 ; i < 12 ; ++i) {
if (strncmp (pDate, months[i], 3) == 0)
break;
}
if (i == 12)
break;
int iMonth = i + 1;
for (i = 0 ; (i < 7) && (*pDate != '\0') ; ++i, ++pDate)
;
int iYear = atoi (pDate);
if ((iYear < 2000) || (iYear > 2010))
break;
// Add 6 months
iMonth += 6;
if (iMonth > 12) {
iMonth -= 12;
iYear += 1;
}
SYSTEMTIME st;
GetSystemTime (&st);
if ((st.wYear < iYear) || ((st.wYear == iYear) && (st.wMonth <= iMonth)))
iRet = TRUE;
break;
}
HKEY hk;
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"Software\\Microsoft\\Bluetooth", 0, KEY_WRITE, &hk)) {
WCHAR szDate[128];
if (! iRet)
wcscpy (szDate, L"EXPIRED");
else
MultiByteToWideChar (CP_ACP, 0, __DATE__, -1, szDate, 128);
RegSetValueEx (hk, L"BETA", 0, REG_SZ, (BYTE *)szDate, (wcslen (szDate) + 1) * sizeof(WCHAR));
}
return iRet;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -