📄 btd.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 Driver
//
//
// Module Name:
//
// btd.cxx
//
// Abstract:
//
// This file implements Bluetooth System Driver
//
//
//------------------------------------------------------------------------------
#include <windows.h>
#define PERSIST_LINK_KEYS 1
#define PERSIST_PINS 1
#if defined (SDK_BUILD)
#undef CP_UTF8
#endif
#include <svsutil.hxx>
#include <bt_debug.h>
#include <bt_os.h>
#include <bt_hcip.h>
#include <bt_ddi.h>
#include <bt_sdp.h>
#include <bthsdpdef.h>
#if defined (UNDER_CE)
#include <service.h>
#include <winsock2.h>
#endif
#include <bt_api.h>
#define BTD_EVENT_BASEBAND_CHANGED 0
#define BTD_EVENT_CONNECTIONS_CHANGED 1
#define BTD_EVENT_SECURITY_CHANGED 2
#define BTD_EVENT_CONNECTIVITY_CHANGED 3
#define BTD_EVENT_DEVICEID_CHANGED 4
#define BTD_EVENT_HARDWARE_CHANGED 5
#define BTD_EVENT_PAIRING_CHANGED 6
#define BTD_EVENT_NUMBER 7
#define BTD_AUTH_RETRY 3
#define BTD_AUTH_SLEEP 1000
#define BTD_POWER_RECHECK 30000
#define BTD_POWER_DELAY 5000
#define CALL_HCI_READ_BD_ADDR 0x01
#define CALL_HCI_CHANGE_LOCAL_NAME 0x02
#define CALL_HCI_INQUIRY 0x03
#define CALL_HCI_QUERY_REMOTE_NAME 0x04
#define CALL_HCI_WRITE_SCAN_ENABLE 0x05
#define CALL_HCI_WRITE_PAGE_TIMEOUT 0x06
#define CALL_HCI_AUTHENTICATE 0x07
#define CALL_HCI_SET_ENCRYPTION 0x08
#define CALL_HCI_READ_SCAN_ENABLE 0x09
#define CALL_HCI_READ_PAGE_TIMEOUT 0x0a
#define CALL_HCI_WRITE_CLASS_OF_DEVICE 0x0b
#define CALL_HCI_READ_CLASS_OF_DEVICE 0x0c
#define CALL_HCI_READ_LOCAL_VERSION 0x0d
#define CALL_HCI_READ_LOCAL_LMP 0x0e
#define CALL_HCI_READ_REMOTE_VERSION 0x0f
#define CALL_HCI_READ_REMOTE_LMP 0x10
#define CALL_HCI_WRITE_AUTHN_ENABLE 0x11
#define CALL_HCI_READ_AUTHN_ENABLE 0x12
#define CALL_HCI_WRITE_LINK_POLICY 0x13
#define CALL_HCI_READ_LINK_POLICY 0x14
#define CALL_HCI_ENTER_HOLD_MODE 0x15
#define CALL_HCI_ENTER_SNIFF_MODE 0x16
#define CALL_HCI_EXIT_SNIFF_MODE 0x17
#define CALL_HCI_ENTER_PARK_MODE 0x18
#define CALL_HCI_EXIT_PARK_MODE 0x19
#define CALL_HCI_CANCEL_INQUIRY 0x1a
#define CALL_L2CAP_CLEAN_UP_L2CAP 0x1b
#define CALL_HCI_EVENTFILTER 0x20
#define CALL_HCI_ACL_CONNECT 0x21
#define CALL_HCI_SCO_CONNECT 0x22
#define CALL_HCI_BASEBAND_DISCONNECT 0x23
#define CALL_HCI_SCO_ACCEPT 0x24
#define COMMAND_PERIODIC_TIMEOUT 5000
#define MAX_PENDING_PIN_REQUESTS 16
struct VersionInformation {
unsigned char hci_version; // Local only
unsigned short hci_revision; // Local only
unsigned char lmp_version;
unsigned short manufacturer_name;
unsigned short lmp_subversion;
};
struct SCall {
SCall *pNext;
HANDLE hProcOwner;
HANDLE hEvent;
int iResult;
unsigned int fWhat : 8;
unsigned int fComplete : 1;
unsigned int fRetry : 1;
union {
VersionInformation viResult;
BD_ADDR baResult;
DWORD dwResult;
unsigned short usResult;
unsigned char ucResult;
unsigned char ftmResult[8];
struct {
void *pBuffer;
DWORD dwPerms;
BOOL bKMode;
} ptrResult;
};
};
struct Link {
Link *pNext;
BD_ADDR b;
unsigned short h;
unsigned char type;
HANDLE hProcOwner;
};
struct Security {
Security *pNext;
BD_ADDR b;
int csize; // 0 for links
unsigned char ucdata[16];
};
struct PINRequest {
PINRequest *pNext;
DWORD dwTimeOutCookie;
unsigned int fConnectionLocked : 1;
BD_ADDR ba;
};
struct InquiryBuffer : public SVSRefObj {
BT_ADDR ba[256];
unsigned int cod[256];
unsigned char psm[256];
unsigned char pspm[256];
unsigned char psrm[256];
unsigned short co[256];
int cb;
HANDLE hWakeUpAll;
int iRes;
InquiryBuffer (void) {
cb = 0;
iRes = ERROR_SUCCESS;
hWakeUpAll = CreateEvent (NULL, TRUE, FALSE, NULL);
}
~InquiryBuffer (void) {
CloseHandle (hWakeUpAll);
}
};
static int btshell_CloseDriverInstance (void);
static int btshell_InquiryComplete (void *pUserContext, void *pCallContext, unsigned char status);
static int btshell_InquiryResult (void *pUserContext, void *pCallContext, BD_ADDR *pba, unsigned char page_scan_repetition_mode_list, unsigned char page_scan_period_mode, unsigned char page_scan_mode, unsigned int class_of_device, unsigned short clock_offset);
static int btshell_RemoteNameDone (void *pUserContext, void *pCallContext, unsigned char status, BD_ADDR *pba, unsigned char utf_name[248]);
static int btshell_PINCodeRequestEvent (void *pUserContext, void *pCallContext, BD_ADDR *pba);
static int btshell_LinkKeyRequestEvent (void *pUserContext, void *pCallContext, BD_ADDR *pba);
static int btshell_LinkKeyNotificationEvent (void *pUserContext, void *pCallContext, BD_ADDR *pba, unsigned char link_key[16], unsigned char key_type);
static int btshell_AuthenticationCompleteEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle);
static int btshell_EncryptionChangeEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned char encryption_enable);
static int btshell_ReadRemoteSupportedFeaturesCompleteEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned char lmp_features[8]);
static int btshell_ReadRemoteVersionInformationCompleteEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned char lmp_version, unsigned short manufacturers_name, unsigned short lmp_subversion);
static int btshell_ModeChangeEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned char current_more, unsigned short interval);
static int btshell_ConnectionCompleteEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, BD_ADDR *pba, unsigned char link_type, unsigned char encryption_mode);
static int btshell_DisconnectionCompleteEvent (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned char reason);
static int btshell_ConnectionRequestEvent (void *pUserContext, void *pCallContext, BD_ADDR *pba, unsigned int class_of_device, unsigned char link_type);
static int btshell_hStackEvent (void *pUserContext, int iEvent, void *pEventContext);
static int btshell_LocalNameDone (void *pCallContext, unsigned char status);
static int btshell_Inquiry_Out (void *pCallContext, unsigned char status);
static int btshell_BDADDR_Out (void *pCallContext, unsigned char status, BD_ADDR *pba);
static int btshell_RemoteName_Out (void *pCallContext, unsigned char status);
static int btshell_WriteScan_Out (void *pCallContext, unsigned char status);
static int btshell_ReadScan_Out (void *pCallContext, unsigned char status, unsigned char mask);
static int btshell_WritePageTimeout_Out (void *pCallContext, unsigned char status);
static int btshell_ReadPageTimeout_Out (void *pCallContext, unsigned char status, unsigned short page);
static int btshell_WriteClassOfDevice_Out (void *pCallContext, unsigned char status);
static int btshell_ReadClassOfDevice_Out (void *pCallContext, unsigned char status, unsigned int cod);
static int btshell_WriteAuthenticationEnable_Out (void *pCallContext, unsigned char status);
static int btshell_ReadAuthenticationEnable_Out (void *pCallContext, unsigned char status, unsigned char ae);
static int btshell_WriteLinkPolicySettings_Out (void *pCallContext, unsigned char status, unsigned short connection_handle);
static int btshell_ReadLinkPolicySettings_Out (void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned short link_policy_settings);
static int btshell_InquiryCancel_Out (void *pCallContext, unsigned char status);
static int btshell_Disconnect_Out (void *pCallContext, unsigned char status);
static int btshell_CreateConnection_Out (void *pCallContext, unsigned char status);
static int btshell_SetEventFilter_Out (void *pCallContext, unsigned char status);
static int btshell_AddSCOConnection_Out(void *pCallContext, unsigned char status);
static int btshell_AcceptConnectionRequest_Out (void *pCallContext, unsigned char status);
static int btshell_security_command_out (void *pCallContext, unsigned char status);
static int btshell_AuthenticationRequested_out (void *pCallContext, unsigned char status);
static int btshell_ReadLocalVersionInformation_Out (void *pCallContext, unsigned char status, unsigned char hci_version, unsigned short hci_revision, unsigned char lmp_version, unsigned short manufacturer_name, unsigned short lmp_subversion);
static int btshell_ReadLocalSupportedFeatures_Out (void *pCallContext, unsigned char status, unsigned char features_mask[8]);
static int btshell_ReadRemoteVersionInformation_Out (void *pCallContext, unsigned char status);
static int btshell_ReadRemoteSupportedFeatures_Out (void *pCallContext, unsigned char status);
static int btshell_HoldMode_Out (void *pCallContext, unsigned char status);
static int btshell_SniffMode_Out (void *pCallContext, unsigned char status);
static int btshell_ParkMode_Out (void *pCallContext, unsigned char status);
static int btshell_ExitSniffMode_Out (void *pCallContext, unsigned char status);
static int btshell_ExitParkMode_Out (void *pCallContext, unsigned char status);
static int btshell_CallAborted (void *pCallContext, int iError);
static int GetHandleForBA (BD_ADDR *pba, unsigned short *phandle);
static int LockL2CAPConnection (BD_ADDR *pba, int fLock);
static BOOL RouteSCOControl(void);
void SdpRemoveRecordsOnProcessExit(HANDLE hDyingProc);
//
// L2CAP link is only to express-abort idle connections...
//
static int btshell_lStackEvent (void *pUserContext, int iEvent, void *pEventContext);
class BTSHELL : public SVSSynch, public SVSRefObj {
public:
SCall *pCalls;
Security *pSecurity;
Link *pLinks;
unsigned int fIsRunning : 1;
unsigned int fConnected : 1;
unsigned int fNoSuspend : 1;
HANDLE hL2CAP;
L2CAP_INTERFACE l2cap_if;
HANDLE hHCI;
HCI_INTERFACE hci_if;
FixedMemDescr *pfmdCalls;
FixedMemDescr *pfmdSecurity;
FixedMemDescr *pfmdLinks;
BD_ADDR b;
HANDLE hNamedEvents[BTD_EVENT_NUMBER];
PINRequest pin_reqs[MAX_PENDING_PIN_REQUESTS];
PINRequest *pRequested;
PINRequest *pInService;
PINRequest *pFree;
HANDLE hAddrEvent;
HANDLE hSecurityUIEvent;
HANDLE hSecurityUIProc;
DWORD dwSecurityProcPermissions;
DWORD dwPINRequestStoreTimeout;
DWORD dwPINRequestProcessTimeout;
SVSCookie ckPowerMonitor;
int cntPowerMonitor;
unsigned int cntAcceptSCO;
void ClearPinRequests (void) {
pFree = pRequested = pInService = NULL;
memset (pin_reqs, 0, sizeof(pin_reqs));
for (int i = 0 ; i < MAX_PENDING_PIN_REQUESTS ; ++i) {
pin_reqs[i].pNext = pFree;
pFree = &pin_reqs[i];
}
}
BTSHELL (void) {
IFDBG(DebugOut (DEBUG_SHELL_TRACE, L"Shell: new BTSHELL\n"));
pCalls = NULL;
pSecurity = NULL;
pLinks = NULL;
fIsRunning = FALSE;
fConnected = FALSE;
fNoSuspend = FALSE;
ckPowerMonitor = 0;
cntPowerMonitor = 0;
cntAcceptSCO = 0;
ClearPinRequests ();
hSecurityUIEvent = NULL;
hSecurityUIProc = NULL;
hAddrEvent = NULL;
dwSecurityProcPermissions = 0;
dwPINRequestStoreTimeout = 0;
dwPINRequestProcessTimeout = 0;
hL2CAP = NULL;
memset (&l2cap_if, 0, sizeof(l2cap_if));
hHCI = NULL;
memset (&hci_if, 0, sizeof(hci_if));
pfmdCalls = pfmdSecurity = pfmdLinks = NULL;
if (! (pfmdCalls = svsutil_AllocFixedMemDescr (sizeof(SCall), 10)))
return;
if (! (pfmdSecurity = svsutil_AllocFixedMemDescr (sizeof(Security), 10)))
return;
if (! (pfmdLinks = svsutil_AllocFixedMemDescr (sizeof(Link), 10)))
return;
hNamedEvents[BTD_EVENT_BASEBAND_CHANGED] = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_BASEBAND_CHANGED);
hNamedEvents[BTD_EVENT_CONNECTIONS_CHANGED] = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_CONNECTIONS_CHANGED);
hNamedEvents[BTD_EVENT_SECURITY_CHANGED] = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_SECURITY_CHANGED);
hNamedEvents[BTD_EVENT_CONNECTIVITY_CHANGED] = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_CONNECTIVITY_CHANGED);
hNamedEvents[BTD_EVENT_DEVICEID_CHANGED] = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_DEVICEID_CHANGED);
hNamedEvents[BTD_EVENT_HARDWARE_CHANGED] = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_HARDWARE_CHANGED);
hNamedEvents[BTD_EVENT_PAIRING_CHANGED] = CreateEvent (NULL, TRUE, FALSE, BTH_NAMEDEVENT_PAIRING_CHANGED);
hAddrEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
L2CAP_EVENT_INDICATION lei;
memset (&lei, 0, sizeof(lei));
lei.l2ca_StackEvent = btshell_lStackEvent;
L2CAP_CALLBACKS lc;
memset (&lc, 0, sizeof(lc));
lc.l2ca_CallAborted = btshell_CallAborted;
int cL2CAPHeaders = 0;
int cL2CAPTrailers = 0;
if (ERROR_SUCCESS != L2CAP_EstablishDeviceContext (this, L2CAP_PSM_MULTIPLE, &lei, &lc, &l2cap_if, &cL2CAPHeaders, &cL2CAPTrailers, &hL2CAP))
return;
HCI_EVENT_INDICATION hei;
memset (&hei, 0, sizeof (hei));
hei.hci_InquiryCompleteEvent = btshell_InquiryComplete;
hei.hci_InquiryResultEvent = btshell_InquiryResult;
hei.hci_RemoteNameRequestCompleteEvent = btshell_RemoteNameDone;
hei.hci_LinkKeyRequestEvent = btshell_LinkKeyRequestEvent;
hei.hci_PINCodeRequestEvent = btshell_PINCodeRequestEvent;
hei.hci_LinkKeyNotificationEvent = btshell_LinkKeyNotificationEvent;
hei.hci_AuthenticationCompleteEvent = btshell_AuthenticationCompleteEvent;
hei.hci_EncryptionChangeEvent = btshell_EncryptionChangeEvent;
hei.hci_ReadRemoteSupportedFeaturesCompleteEvent = btshell_ReadRemoteSupportedFeaturesCompleteEvent;
hei.hci_ReadRemoteVersionInformationCompleteEvent = btshell_ReadRemoteVersionInformationCompleteEvent;
hei.hci_ModeChangeEvent = btshell_ModeChangeEvent;
hei.hci_ConnectionCompleteEvent = btshell_ConnectionCompleteEvent;
hei.hci_DisconnectionCompleteEvent = btshell_DisconnectionCompleteEvent;
hei.hci_ConnectionRequestEvent = btshell_ConnectionRequestEvent;
hei.hci_StackEvent = btshell_hStackEvent;
HCI_CALLBACKS hc;
memset (&hc, 0, sizeof (hc));
hc.hci_ChangeLocalName_Out = btshell_LocalNameDone;
hc.hci_Inquiry_Out = btshell_Inquiry_Out;
hc.hci_InquiryCancel_Out = btshell_InquiryCancel_Out;
hc.hci_ReadBDADDR_Out = btshell_BDADDR_Out;
hc.hci_RemoteNameRequest_Out = btshell_RemoteName_Out;
hc.hci_WriteScanEnable_Out = btshell_WriteScan_Out;
hc.hci_ReadScanEnable_Out = btshell_ReadScan_Out;
hc.hci_WritePageTimeout_Out = btshell_WritePageTimeout_Out;
hc.hci_ReadPageTimeout_Out = btshell_ReadPageTimeout_Out;
hc.hci_WriteClassOfDevice_Out = btshell_WriteClassOfDevice_Out;
hc.hci_ReadClassOfDevice_Out = btshell_ReadClassOfDevice_Out;
hc.hci_WriteAuthenticationEnable_Out = btshell_WriteAuthenticationEnable_Out;
hc.hci_ReadAuthenticationEnable_Out = btshell_ReadAuthenticationEnable_Out;
hc.hci_WriteLinkPolicySettings_Out = btshell_WriteLinkPolicySettings_Out;
hc.hci_ReadLinkPolicySettings_Out = btshell_ReadLinkPolicySettings_Out;
hc.hci_AuthenticationRequested_Out = btshell_AuthenticationRequested_out;
hc.hci_SetConnectionEncryption_Out = btshell_security_command_out;
hc.hci_ReadRemoteSupportedFeatures_Out = btshell_ReadRemoteSupportedFeatures_Out;
hc.hci_ReadRemoteVersionInformation_Out = btshell_ReadRemoteVersionInformation_Out;
hc.hci_ReadLocalSupportedFeatures_Out = btshell_ReadLocalSupportedFeatures_Out;
hc.hci_ReadLocalVersionInformation_Out = btshell_ReadLocalVersionInformation_Out;
hc.hci_HoldMode_Out = btshell_HoldMode_Out;
hc.hci_SniffMode_Out = btshell_SniffMode_Out;
hc.hci_ParkMode_Out = btshell_ParkMode_Out;
hc.hci_ExitSniffMode_Out = btshell_ExitSniffMode_Out;
hc.hci_ExitParkMode_Out = btshell_ExitParkMode_Out;
hc.hci_CreateConnection_Out = btshell_CreateConnection_Out;
hc.hci_Disconnect_Out = btshell_Disconnect_Out;
hc.hci_SetEventFilter_Out = btshell_SetEventFilter_Out;
hc.hci_AddSCOConnection_Out = btshell_AddSCOConnection_Out;
hc.hci_AcceptConnectionRequest_Out = btshell_AcceptConnectionRequest_Out;
hc.hci_CallAborted = btshell_CallAborted;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -