mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Final implementation of all BluetoothAdapter methods
PiperOrigin-RevId: 393009194
This commit is contained in:
committed by
Copybara-Service
parent
62e7c01cd3
commit
81b72ab1bf
@@ -15,7 +15,6 @@
|
|||||||
#include "platform/impl/windows/bluetooth_adapter.h"
|
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
#include <bthdef.h>
|
#include <bthdef.h>
|
||||||
#include <bthioctl.h>
|
#include <bthioctl.h>
|
||||||
@@ -24,6 +23,7 @@
|
|||||||
#include <initguid.h>
|
#include <initguid.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <setupapi.h>
|
#include <setupapi.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <usbiodef.h>
|
#include <usbiodef.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -38,6 +38,14 @@ typedef std::basic_string<TCHAR> tstring;
|
|||||||
// IOCTL to get local radio information
|
// IOCTL to get local radio information
|
||||||
#define BTH_GET_DEVICE_INFO_IOCTL 0x411008
|
#define BTH_GET_DEVICE_INFO_IOCTL 0x411008
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 64
|
||||||
|
#define FILE_NAME_SIZE 1024
|
||||||
|
|
||||||
|
#define REGISTRY_QUERY_FORMAT \
|
||||||
|
"SYSTEM\\ControlSet001\\Enum\\%s\\Device Parameters"
|
||||||
|
|
||||||
|
#define BLUETOOTH_RADIO_REGISTRY_NAME_KEY "Local Name"
|
||||||
|
|
||||||
namespace location {
|
namespace location {
|
||||||
namespace nearby {
|
namespace nearby {
|
||||||
namespace windows {
|
namespace windows {
|
||||||
@@ -92,7 +100,90 @@ bool BluetoothAdapter::SetScanMode(ScanMode scan_mode) {
|
|||||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
|
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
|
||||||
// Returns an empty string on error
|
// Returns an empty string on error
|
||||||
// TODO(b/184975123): replace with real implementation.
|
// TODO(b/184975123): replace with real implementation.
|
||||||
std::string BluetoothAdapter::GetName() const { return "Un-implemented"; }
|
std::string BluetoothAdapter::GetName() const {
|
||||||
|
char *instanceID = GetGenericBluetoothAdapterInstanceID();
|
||||||
|
|
||||||
|
if (instanceID == NULL) {
|
||||||
|
NEARBY_LOGS(ERROR)
|
||||||
|
<< __func__ << ": Failed to get Generic Bluetooth Adapter InstanceID";
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
// Add 1 to length to get size (including null)
|
||||||
|
// Modify the InstanceID to the format that the Registry expects
|
||||||
|
char *instanceIDModified = new char[(strlen(instanceID) + 1) * sizeof(char)];
|
||||||
|
absl::SNPrintF(instanceIDModified,
|
||||||
|
size_t((strlen(instanceID) + 1) * sizeof(char)), "%s",
|
||||||
|
instanceID);
|
||||||
|
find_and_replace(instanceIDModified, "\\", "#");
|
||||||
|
|
||||||
|
// Change radio module local name in registry
|
||||||
|
HKEY hKey;
|
||||||
|
char rmLocalNameKey[FILE_NAME_SIZE] = {0};
|
||||||
|
LSTATUS ret;
|
||||||
|
|
||||||
|
absl::SNPrintF(rmLocalNameKey, sizeof(rmLocalNameKey), REGISTRY_QUERY_FORMAT,
|
||||||
|
instanceID);
|
||||||
|
|
||||||
|
// Opens the specified registry key.
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexa
|
||||||
|
ret = RegOpenKeyExA(
|
||||||
|
HKEY_LOCAL_MACHINE, // A handle to an open registry key, using
|
||||||
|
// predefined key for local machine
|
||||||
|
rmLocalNameKey, // The name of the registry subkey to be opened.
|
||||||
|
0L, // Specifies the option to apply when opening the key.
|
||||||
|
KEY_QUERY_VALUE, // A mask that specifies the desired access rights to
|
||||||
|
// the key to be opened.
|
||||||
|
&hKey); // A pointer to a variable that receives a handle to the opened
|
||||||
|
// key
|
||||||
|
|
||||||
|
if (ret == ERROR_SUCCESS) {
|
||||||
|
BYTE rmLocalName[FILE_NAME_SIZE] = {0};
|
||||||
|
DWORD rmLocalNameSize = FILE_NAME_SIZE;
|
||||||
|
DWORD valueType;
|
||||||
|
|
||||||
|
LSTATUS status =
|
||||||
|
// Retrieves the type and data for the specified value name associated
|
||||||
|
// with an open registry key.
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa
|
||||||
|
RegQueryValueExA(
|
||||||
|
hKey, // A handle to an open registry key.
|
||||||
|
BLUETOOTH_RADIO_REGISTRY_NAME_KEY, // The name of the registry
|
||||||
|
// value.
|
||||||
|
nullptr, // This parameter is reserved and must be NULL.
|
||||||
|
&valueType, // A pointer to a variable that receives a code
|
||||||
|
// indicating the type of data stored in the
|
||||||
|
// specified value.
|
||||||
|
&rmLocalName[0], // A pointer to a buffer that receives the
|
||||||
|
// value's data.
|
||||||
|
&rmLocalNameSize); // A pointer to a variable that specifies the
|
||||||
|
// size of the buffer pointed to by the lpData
|
||||||
|
// parameter, in bytes.
|
||||||
|
|
||||||
|
// Closes a handle to the specified registry key.
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
|
||||||
|
if (status == ERROR_SUCCESS) {
|
||||||
|
char str[FILE_NAME_SIZE]{0};
|
||||||
|
memcpy(str, rmLocalName, rmLocalNameSize);
|
||||||
|
return std::string(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The local name is not in the registry, return the machine name
|
||||||
|
char localName[FILE_NAME_SIZE];
|
||||||
|
DWORD nameSize = FILE_NAME_SIZE;
|
||||||
|
|
||||||
|
// Retrieves the NetBIOS name of the local computer.
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcomputernamea
|
||||||
|
if (GetComputerNameA(localName, &nameSize)) {
|
||||||
|
return std::string(localName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here, we couldn't get a local name, this should never happen
|
||||||
|
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get any radio name";
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
|
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
|
||||||
bool BluetoothAdapter::SetName(absl::string_view name) {
|
bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||||
@@ -114,16 +205,16 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
|||||||
find_and_replace(instanceIDModified, "\\", "#");
|
find_and_replace(instanceIDModified, "\\", "#");
|
||||||
|
|
||||||
HANDLE hDevice;
|
HANDLE hDevice;
|
||||||
char fileName[1024] = {0};
|
char fileName[FILE_NAME_SIZE] = {0};
|
||||||
|
|
||||||
// defined in usbiodef.h
|
// defined in usbiodef.h
|
||||||
const GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
|
const GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
|
||||||
|
|
||||||
OLECHAR guidOleStr[64];
|
OLECHAR guidOleStr[BUFFER_SIZE];
|
||||||
int oleBufferLen = 64;
|
int oleBufferLen = BUFFER_SIZE;
|
||||||
|
|
||||||
char guidStr[64];
|
char guidStr[BUFFER_SIZE];
|
||||||
int bufferLen = 64;
|
int bufferLen = BUFFER_SIZE;
|
||||||
BOOL defaultCharUsed;
|
BOOL defaultCharUsed;
|
||||||
|
|
||||||
// Converts a globally unique identifier (GUID) into a string of printable
|
// Converts a globally unique identifier (GUID) into a string of printable
|
||||||
@@ -172,8 +263,16 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
|||||||
|
|
||||||
// Creates or opens a file or I/O device.
|
// Creates or opens a file or I/O device.
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
|
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
|
||||||
hDevice =
|
hDevice = CreateFileA(
|
||||||
CreateFileA(fileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
fileName, // The name of the file or device to be created or opened.
|
||||||
|
GENERIC_WRITE, // The requested access to the file or device.
|
||||||
|
0, // The requested sharing mode of the file or device.
|
||||||
|
NULL, // A pointer to a SECURITY_ATTRIBUTES structure.
|
||||||
|
OPEN_EXISTING, // An action to take on a file or device that exists or
|
||||||
|
// does not exist.
|
||||||
|
0, // The file or device attributes and flags.
|
||||||
|
NULL); // A valid handle to a template file with the GENERIC_READ access
|
||||||
|
// right. This parameter can be NULL.
|
||||||
|
|
||||||
delete[] instanceIDModified;
|
delete[] instanceIDModified;
|
||||||
|
|
||||||
@@ -185,18 +284,23 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
|||||||
|
|
||||||
// Change radio module local name in registry
|
// Change radio module local name in registry
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
char rmLocalNameKey[1024] = {0};
|
char rmLocalNameKey[FILE_NAME_SIZE] = {0};
|
||||||
LSTATUS ret;
|
LSTATUS ret;
|
||||||
|
|
||||||
absl::SNPrintF(rmLocalNameKey, sizeof(rmLocalNameKey),
|
absl::SNPrintF(rmLocalNameKey, sizeof(rmLocalNameKey), REGISTRY_QUERY_FORMAT,
|
||||||
"SYSTEM\\ControlSet001\\Enum\\%s\\Device Parameters",
|
|
||||||
instanceID);
|
instanceID);
|
||||||
|
|
||||||
// Opens the specified registry key. Note that key names are not case
|
// Opens the specified registry key. Note that key names are not case
|
||||||
// sensitive.
|
// sensitive.
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexa
|
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexa
|
||||||
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, rmLocalNameKey, 0L, KEY_SET_VALUE,
|
ret = RegOpenKeyExA(
|
||||||
&hKey);
|
HKEY_LOCAL_MACHINE, // A handle to an open registry key.
|
||||||
|
rmLocalNameKey, // The name of the registry subkey to be opened.
|
||||||
|
0L, // Specifies the option to apply when opening the key.
|
||||||
|
KEY_SET_VALUE, // A mask that specifies the desired access rights to the
|
||||||
|
// key to be opened.
|
||||||
|
&hKey); // A pointer to a variable that receives a handle to the opened
|
||||||
|
// key.
|
||||||
|
|
||||||
if (ret != ERROR_SUCCESS) {
|
if (ret != ERROR_SUCCESS) {
|
||||||
NEARBY_LOGS(ERROR) << __func__
|
NEARBY_LOGS(ERROR) << __func__
|
||||||
@@ -206,9 +310,15 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
|||||||
|
|
||||||
// Sets the data and type of a specified value under a registry key.
|
// Sets the data and type of a specified value under a registry key.
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexa
|
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexa
|
||||||
ret = RegSetValueExA(hKey, "Local Name", 0, REG_BINARY,
|
ret = RegSetValueExA(
|
||||||
(LPBYTE)std::string(name).c_str(),
|
hKey, // A handle to an open registry key
|
||||||
strlen(std::string(name).c_str()));
|
BLUETOOTH_RADIO_REGISTRY_NAME_KEY, // The name of the value to be set.
|
||||||
|
0, // This parameter is reserved and must be zero.
|
||||||
|
REG_BINARY, // The type of data pointed to by the lpData parameter.
|
||||||
|
(LPBYTE)std::string(name).c_str(), // The data to be stored.
|
||||||
|
strlen(
|
||||||
|
std::string(name).c_str())); // The size of the information pointed
|
||||||
|
// to by the lpData parameter, in bytes.
|
||||||
|
|
||||||
if (ret != ERROR_SUCCESS) {
|
if (ret != ERROR_SUCCESS) {
|
||||||
NEARBY_LOGS(ERROR) << __func__
|
NEARBY_LOGS(ERROR) << __func__
|
||||||
@@ -229,8 +339,19 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
|||||||
// Sends a control code directly to a specified device driver, causing the
|
// Sends a control code directly to a specified device driver, causing the
|
||||||
// corresponding device to perform the corresponding operation.
|
// corresponding device to perform the corresponding operation.
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol
|
// https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol
|
||||||
if (!DeviceIoControl(hDevice, BTH_GET_DEVICE_INFO_IOCTL, &reload, 4, NULL, 0,
|
if (!DeviceIoControl(
|
||||||
&bytes, NULL)) {
|
hDevice, // A handle to the device on which the operation is to be
|
||||||
|
// performed.
|
||||||
|
BTH_GET_DEVICE_INFO_IOCTL, // The control code for the operation.
|
||||||
|
&reload, // A pointer to the input buffer that contains the data
|
||||||
|
// required to perform the operation.
|
||||||
|
sizeof(reload), // The size of the input buffer, in bytes.
|
||||||
|
NULL, // A pointer to the output buffer that is to receive the data
|
||||||
|
// returned by the operation.
|
||||||
|
0, // The size of the output buffer, in bytes.
|
||||||
|
&bytes, // A pointer to a variable that receives the size of the data
|
||||||
|
// stored in the output buffer, in bytes.
|
||||||
|
NULL)) { // A pointer to an OVERLAPPED structure.
|
||||||
NEARBY_LOGS(ERROR)
|
NEARBY_LOGS(ERROR)
|
||||||
<< __func__
|
<< __func__
|
||||||
<< ": Failed to update radio module local name. Error code: "
|
<< ": Failed to update radio module local name. Error code: "
|
||||||
@@ -243,7 +364,7 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
||||||
const char *strReplace) {
|
const char *strReplace) const {
|
||||||
std::string s = std::string(source);
|
std::string s = std::string(source);
|
||||||
std::string f = std::string(strFind);
|
std::string f = std::string(strFind);
|
||||||
std::string r = std::string(strReplace);
|
std::string r = std::string(strReplace);
|
||||||
@@ -256,7 +377,7 @@ void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
|||||||
memcpy(source, s.c_str(), s.size());
|
memcpy(source, s.c_str(), s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) {
|
char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) const {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
CONFIGRET r;
|
CONFIGRET r;
|
||||||
HDEVINFO hDevInfo;
|
HDEVINFO hDevInfo;
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ class BluetoothAdapter : public api::BluetoothAdapter {
|
|||||||
windows_bluetooth_adapter_;
|
windows_bluetooth_adapter_;
|
||||||
|
|
||||||
IRadio windows_bluetooth_radio_;
|
IRadio windows_bluetooth_radio_;
|
||||||
char *GetGenericBluetoothAdapterInstanceID(void);
|
char *GetGenericBluetoothAdapterInstanceID(void) const;
|
||||||
void find_and_replace(char *source, const char *strFind,
|
void find_and_replace(char *source, const char *strFind,
|
||||||
const char *strReplace);
|
const char *strReplace) const;
|
||||||
ScanMode scan_mode_ = ScanMode::kNone;
|
ScanMode scan_mode_ = ScanMode::kNone;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -85,12 +85,12 @@ void BluetoothClassicMedium::InitializeDeviceWatcher() {
|
|||||||
nullptr, // additionalProperties
|
nullptr, // additionalProperties
|
||||||
DeviceInformationKind::AssociationEndpoint); // kind
|
DeviceInformationKind::AssociationEndpoint); // kind
|
||||||
|
|
||||||
// An app must subscribe to all of the added, removed, and updated events to
|
// An app must subscribe to all of the added, removed, and updated events to
|
||||||
// be notified when there are device additions, removals or updates. If an app
|
// be notified when there are device additions, removals or updates. If an
|
||||||
// handles only the added event, it will not receive an update if a device is
|
// app handles only the added event, it will not receive an update if a
|
||||||
// added to the system after the initial device enumeration completes.
|
// device is added to the system after the initial device enumeration
|
||||||
// register event handlers before starting the watcher
|
// completes. register event handlers before starting the watcher
|
||||||
//
|
|
||||||
// Event that is raised when a device is added to the collection enumerated
|
// Event that is raised when a device is added to the collection enumerated
|
||||||
// by the DeviceWatcher.
|
// by the DeviceWatcher.
|
||||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348
|
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348
|
||||||
|
|||||||
@@ -19,11 +19,12 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
|
||||||
#include "absl/strings/str_format.h"
|
|
||||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "platform/api/bluetooth_adapter.h"
|
||||||
|
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||||
|
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||||
|
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||||
|
|
||||||
// TODO(jfcarroll): Find a way to mock winrt components in order to properly
|
// TODO(jfcarroll): Find a way to mock winrt components in order to properly
|
||||||
// unit test this. Once that's done, unit tests can be written, in a later C/L.
|
// unit test this. Once that's done, unit tests can be written, in a later C/L.
|
||||||
@@ -61,8 +62,17 @@ void device_lost_cb(location::nearby::api::BluetoothDevice& device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(TestCaseName, TestName) {
|
TEST(TestCaseName, TestName) {
|
||||||
|
auto bluetoothAdapter = location::nearby::windows::BluetoothAdapter();
|
||||||
|
|
||||||
|
std::string bluetoothAdapterName = bluetoothAdapter.GetName();
|
||||||
|
bluetoothAdapter.SetName("BluetoothTestName");
|
||||||
|
bluetoothAdapterName = bluetoothAdapter.GetName();
|
||||||
|
bluetoothAdapter.SetName("");
|
||||||
|
bluetoothAdapterName = bluetoothAdapter.GetName();
|
||||||
|
|
||||||
std::unique_ptr<location::nearby::windows::BluetoothClassicMedium> bcm =
|
std::unique_ptr<location::nearby::windows::BluetoothClassicMedium> bcm =
|
||||||
std::make_unique<location::nearby::windows::BluetoothClassicMedium>();
|
std::make_unique<location::nearby::windows::BluetoothClassicMedium>(
|
||||||
|
bluetoothAdapter);
|
||||||
|
|
||||||
bcm->StartDiscovery(
|
bcm->StartDiscovery(
|
||||||
location::nearby::api::BluetoothClassicMedium::DiscoveryCallback{
|
location::nearby::api::BluetoothClassicMedium::DiscoveryCallback{
|
||||||
@@ -74,10 +84,14 @@ TEST(TestCaseName, TestName) {
|
|||||||
Sleep(30000);
|
Sleep(30000);
|
||||||
|
|
||||||
auto currentDevice = deviceList["DC:DC:E2:F2:B5:99"];
|
auto currentDevice = deviceList["DC:DC:E2:F2:B5:99"];
|
||||||
auto serviceUuid = winrt::Windows::Devices::Bluetooth::Rfcomm::
|
auto serviceUuid = winrt::to_string(
|
||||||
RfcommServiceId::GenericFileTransfer();
|
winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId::SerialPort()
|
||||||
|
.AsString());
|
||||||
|
|
||||||
location::nearby::CancellationFlag cancellationFlag;
|
location::nearby::CancellationFlag cancellationFlag;
|
||||||
bcm->ConnectToService(*currentDevice, "a82efa21-ae5c-3dde-9bbc-f16da7b16c5a",
|
bcm->ConnectToService(*currentDevice,
|
||||||
|
// "a82efa21-ae5c-3dde-9bbc-f16da7b16c5a",
|
||||||
|
"00001101-0000-1000-8000-00805F9B34FB",
|
||||||
&cancellationFlag);
|
&cancellationFlag);
|
||||||
|
|
||||||
EXPECT_EQ(1, 1);
|
EXPECT_EQ(1, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user