mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Add an initial BLE v2 implementation.
This commit is contained in:
@@ -55,8 +55,10 @@ cc_library(
|
||||
name = "comm",
|
||||
hdrs = [
|
||||
"avahi.h",
|
||||
"ble_gatt_server.h",
|
||||
"ble_medium.h",
|
||||
"ble_v2_medium.h",
|
||||
"ble_v2_server_socket.h",
|
||||
"bluetooth_adapter.h",
|
||||
"bluetooth_bluez_profile.h",
|
||||
"bluetooth_classic_device.h",
|
||||
@@ -66,6 +68,12 @@ cc_library(
|
||||
"bluetooth_devices.h",
|
||||
"bluetooth_pairing.h",
|
||||
"bluez.h",
|
||||
"bluez_advertisement_monitor.h",
|
||||
"bluez_advertisement_monitor_manager.h",
|
||||
"bluez_gatt_characteristic.h",
|
||||
"bluez_gatt_manager.h",
|
||||
"bluez_gatt_service.h",
|
||||
"bluez_le_advertisement.h",
|
||||
"dbus.h",
|
||||
"network_manager.h",
|
||||
"network_manager_active_connection.h",
|
||||
@@ -125,6 +133,8 @@ cc_library(
|
||||
name = "linux",
|
||||
srcs = [
|
||||
"avahi.cc",
|
||||
"ble_gatt_server.cc",
|
||||
"ble_v2_medium.cc",
|
||||
"bluetooth_adapter.cc",
|
||||
"bluetooth_bluez_profile.cc",
|
||||
"bluetooth_classic_socket.cc",
|
||||
@@ -134,6 +144,10 @@ cc_library(
|
||||
"bluetooth_devices.cc",
|
||||
"bluetooth_pairing.cc",
|
||||
"bluez.cc",
|
||||
"bluez_advertisement_monitor.cc",
|
||||
"bluez_gatt_characteristic.cc",
|
||||
"bluez_gatt_service.cc",
|
||||
"bluez_le_advertisement.cc",
|
||||
"dbus.cc",
|
||||
"executor.cc",
|
||||
"network_manager.cc",
|
||||
@@ -224,6 +238,7 @@ cc_test(
|
||||
"atomic_boolean_test.cc",
|
||||
"atomic_reference_test.cc",
|
||||
"mutex_test.cc",
|
||||
"utils_test.cc",
|
||||
# "bluetooth_adapter_test.cc",
|
||||
# "crypto_test.cc",
|
||||
# "device_info_test.cc",
|
||||
@@ -236,7 +251,6 @@ cc_test(
|
||||
# "submittable_executor_test.cc",
|
||||
# "thread_pool_test.cc",
|
||||
# "timer_test.cc",
|
||||
# "utils_test.cc",
|
||||
],
|
||||
tags = ["notap"],
|
||||
deps = [
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/linux/ble_gatt_server.h"
|
||||
#include "absl/strings/substitute.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_characteristic.h"
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_manager.h"
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_service.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_service_server.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
absl::optional<api::ble_v2::GattCharacteristic>
|
||||
GattServer::CreateCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid,
|
||||
api::ble_v2::GattCharacteristic::Permission permission,
|
||||
api::ble_v2::GattCharacteristic::Property property) {
|
||||
absl::MutexLock lock(&services_mutex_);
|
||||
if (services_.count(service_uuid) == 1) {
|
||||
if (services_[service_uuid]->AddCharacteristic(
|
||||
service_uuid, characteristic_uuid, permission, property)) {
|
||||
api::ble_v2::GattCharacteristic characteristic{
|
||||
characteristic_uuid, service_uuid, permission, property};
|
||||
return characteristic;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto count = services_.size();
|
||||
auto service = std::make_unique<bluez::GattService>(
|
||||
system_bus_, count, service_uuid, server_cb_, devices_);
|
||||
try {
|
||||
service->emitInterfacesAddedSignal(
|
||||
{org::bluez::GattService1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error& e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesAdded signal for object path "
|
||||
<< service->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (service->AddCharacteristic(service_uuid, characteristic_uuid, permission,
|
||||
property)) {
|
||||
bluez::GattManager manager(system_bus_, adapter_.GetObjectPath());
|
||||
try {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": registering service "
|
||||
<< service->getObjectPath();
|
||||
manager.RegisterApplication("/", {});
|
||||
} catch (const sdbus::Error& e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&manager, "RegisterApplication", e);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
services_.insert({service_uuid, std::move(service)});
|
||||
|
||||
api::ble_v2::GattCharacteristic characteristic{
|
||||
characteristic_uuid, service_uuid, permission, property};
|
||||
return characteristic;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool GattServer::UpdateCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
const nearby::ByteArray& value) {
|
||||
std::shared_ptr<bluez::GattCharacteristic> chr = nullptr;
|
||||
{
|
||||
absl::ReaderMutexLock lock(&services_mutex_);
|
||||
if (services_.count(characteristic.service_uuid) == 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": GATT Service "
|
||||
<< std::string{characteristic.service_uuid}
|
||||
<< " doesn't exist";
|
||||
return false;
|
||||
}
|
||||
chr = services_[characteristic.service_uuid]->GetCharacteristic(
|
||||
characteristic.uuid);
|
||||
}
|
||||
if (chr == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Characteristic "
|
||||
<< std::string{characteristic.uuid}
|
||||
<< " does not exist under service "
|
||||
<< std::string{characteristic.service_uuid};
|
||||
return false;
|
||||
}
|
||||
assert(chr != nullptr);
|
||||
chr->Update(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
absl::Status GattServer::NotifyCharacteristicChanged(
|
||||
const api::ble_v2::GattCharacteristic& characteristic, bool confirm,
|
||||
const ByteArray& new_value) {
|
||||
std::shared_ptr<bluez::GattCharacteristic> chr = nullptr;
|
||||
{
|
||||
absl::ReaderMutexLock lock(&services_mutex_);
|
||||
if (services_.count(characteristic.service_uuid) == 0) {
|
||||
return absl::NotFoundError(
|
||||
absl::Substitute("Service $0 doesn't exist",
|
||||
std::string{characteristic.service_uuid}));
|
||||
}
|
||||
chr = services_[characteristic.service_uuid]->GetCharacteristic(
|
||||
characteristic.uuid);
|
||||
}
|
||||
if (chr == nullptr) {
|
||||
return absl::NotFoundError(
|
||||
absl::Substitute("characteristic $0 doesn't exist under service $1",
|
||||
std::string{characteristic.uuid},
|
||||
std::string{characteristic.service_uuid}));
|
||||
}
|
||||
|
||||
return chr->NotifyChanged(confirm, new_value);
|
||||
}
|
||||
|
||||
void GattServer::Stop() {
|
||||
bluez::GattManager manager(system_bus_, adapter_.GetObjectPath());
|
||||
absl::MutexLock lock(&services_mutex_);
|
||||
for (auto& [uuid, service] : services_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Unregistering service "
|
||||
<< service->getObjectPath();
|
||||
try {
|
||||
manager.UnregisterApplication("/");
|
||||
} catch (const sdbus::Error& e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&manager, "UnregisterApplication", e);
|
||||
}
|
||||
}
|
||||
// services_.clear();
|
||||
}
|
||||
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_API_BLE_GATT_SERVER_H_
|
||||
#define PLATFORM_IMPL_LINUX_API_BLE_GATT_SERVER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/bluetooth_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_devices.h"
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_service.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
class LocalBlePeripheral : public api::ble_v2::BlePeripheral {
|
||||
public:
|
||||
explicit LocalBlePeripheral(BluetoothAdapter& adapter) : adapter_(adapter) {
|
||||
unique_id_ = BluetoothUtils::ToNumber(adapter_.GetMacAddress());
|
||||
}
|
||||
|
||||
std::string GetAddress() const override { return adapter_.GetMacAddress(); }
|
||||
UniqueId GetUniqueId() const override { return unique_id_; }
|
||||
|
||||
private:
|
||||
BluetoothAdapter adapter_;
|
||||
UniqueId unique_id_;
|
||||
};
|
||||
|
||||
class GattServer : public api::ble_v2::GattServer {
|
||||
public:
|
||||
GattServer(const GattServer&) = delete;
|
||||
GattServer(GattServer&&) = delete;
|
||||
GattServer& operator=(const GattServer&) = delete;
|
||||
GattServer& operator=(GattServer&&) = delete;
|
||||
|
||||
explicit GattServer(sdbus::IConnection& system_bus, BluetoothAdapter& adapter,
|
||||
std::shared_ptr<BluetoothDevices> devices,
|
||||
api::ble_v2::ServerGattConnectionCallback server_cb)
|
||||
: system_bus_(system_bus),
|
||||
devices_(std::move(devices)),
|
||||
adapter_(adapter),
|
||||
local_peripheral_(adapter_),
|
||||
server_cb_(std::make_shared<api::ble_v2::ServerGattConnectionCallback>(
|
||||
std::move(server_cb))) {}
|
||||
~GattServer() override = default;
|
||||
|
||||
api::ble_v2::BlePeripheral& GetBlePeripheral() override {
|
||||
return local_peripheral_;
|
||||
}
|
||||
absl::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid,
|
||||
api::ble_v2::GattCharacteristic::Permission permission,
|
||||
api::ble_v2::GattCharacteristic::Property property) override;
|
||||
bool UpdateCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
const nearby::ByteArray& value) override;
|
||||
absl::Status NotifyCharacteristicChanged(
|
||||
const api::ble_v2::GattCharacteristic& characteristic, bool confirm,
|
||||
const ByteArray& new_value) override;
|
||||
void Stop() override;
|
||||
|
||||
private:
|
||||
sdbus::IConnection& system_bus_;
|
||||
std::shared_ptr<BluetoothDevices> devices_;
|
||||
BluetoothAdapter adapter_;
|
||||
LocalBlePeripheral local_peripheral_;
|
||||
|
||||
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb_;
|
||||
absl::Mutex services_mutex_;
|
||||
absl::flat_hash_map<Uuid, std::unique_ptr<bluez::GattService>> services_
|
||||
ABSL_GUARDED_BY(services_mutex_);
|
||||
};
|
||||
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
#endif
|
||||
@@ -0,0 +1,436 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include <sdbus-c++/IProxy.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include <absl/functional/any_invocable.h>
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/ble_gatt_server.h"
|
||||
#include "internal/platform/implementation/linux/ble_v2_medium.h"
|
||||
#include "internal/platform/implementation/linux/bluez_advertisement_monitor.h"
|
||||
#include "internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h"
|
||||
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/advertisement_monitor_server.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/le_advertisement_manager_client.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
BleV2Medium::BleV2Medium(sdbus::IConnection &system_bus,
|
||||
BluetoothAdapter &adapter)
|
||||
: system_bus_(system_bus),
|
||||
adapter_(adapter),
|
||||
devices_(std::make_unique<BluetoothDevices>(
|
||||
system_bus_, adapter_.GetObjectPath(), observers_)),
|
||||
adv_monitor_manager_(
|
||||
bluez::AdvertisementMonitorManager::
|
||||
DiscoverAdvertisementMonitorManager(system_bus, adapter_)),
|
||||
adv_manager_(
|
||||
std::make_unique<bluez::LEAdvertisementManager>(system_bus, adapter)),
|
||||
cur_adv_(nullptr) {
|
||||
if (adv_monitor_manager_) {
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< __func__
|
||||
<< ": Registering path / with AdvertisementMonitorManager at "
|
||||
<< adv_monitor_manager_->getObjectPath();
|
||||
try {
|
||||
adv_monitor_manager_->RegisterMonitor("/");
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(adv_monitor_manager_, "RegisterMonitor", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BleV2Medium::StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData &advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters) {
|
||||
if (!adapter_.IsEnabled()) {
|
||||
NEARBY_LOGS(WARNING) << "BLE cannot start advertising because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (advertising_data.service_data.empty()) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "BLE cannot start to advertise due to invalid service data.";
|
||||
return false;
|
||||
}
|
||||
|
||||
absl::MutexLock lock(&cur_adv_mutex_);
|
||||
if (cur_adv_ != nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Advertising is already enabled for this medium.";
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_adv_ = bluez::LEAdvertisement::CreateLEAdvertisement(
|
||||
system_bus_, advertising_data, advertise_set_parameters);
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Registering advertisement "
|
||||
<< cur_adv_->getObjectPath() << " on bluetooth adapter "
|
||||
<< adapter_.GetObjectPath();
|
||||
|
||||
try {
|
||||
adv_manager_->RegisterAdvertisement(cur_adv_->getObjectPath(), {});
|
||||
} catch (const sdbus::Error &e) {
|
||||
cur_adv_ = nullptr;
|
||||
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "RegisterAdvertisement", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2Medium::StopAdvertising() {
|
||||
absl::MutexLock lock(&cur_adv_mutex_);
|
||||
if (cur_adv_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Advertising is not enabled.";
|
||||
return false;
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Unregistering advertisement object "
|
||||
<< cur_adv_->getObjectPath();
|
||||
|
||||
try {
|
||||
adv_manager_->UnregisterAdvertisement(cur_adv_->getObjectPath());
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisement", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_adv_ = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleMedium::AdvertisingSession>
|
||||
BleV2Medium::StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData &advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters,
|
||||
AdvertisingCallback callback) {
|
||||
if (!adapter_.IsEnabled()) {
|
||||
NEARBY_LOGS(WARNING) << ": BLE cannot start advertising because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (advertising_data.service_data.empty()) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< ": BLE cannot start to advertise due to invalid service data.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<sdbus::IProxy> proxy =
|
||||
sdbus::createProxy(system_bus_, "org.bluez", adapter_.GetObjectPath());
|
||||
proxy->finishRegistration();
|
||||
|
||||
std::shared_ptr<AdvertisingCallback> shared_cb =
|
||||
std::make_shared<AdvertisingCallback>(std::move(callback));
|
||||
|
||||
absl::MutexLock lock(&advs_mutex_);
|
||||
advs_.push_front(bluez::LEAdvertisement::CreateLEAdvertisement(
|
||||
system_bus_, advertising_data, advertise_set_parameters));
|
||||
auto adv_it = advs_.begin();
|
||||
|
||||
auto pending_call =
|
||||
proxy->callMethodAsync("RegisterAdvertisement")
|
||||
.onInterface(org::bluez::LEAdvertisingManager1_proxy::INTERFACE_NAME)
|
||||
.withArguments((*adv_it)->getObjectPath(),
|
||||
std::map<std::string, sdbus::Variant>{})
|
||||
.uponReplyInvoke(
|
||||
[this, proxy, shared_cb, adv_it](const sdbus::Error *error) {
|
||||
if (error != nullptr && error->isValid()) {
|
||||
{
|
||||
absl::MutexLock lock(&advs_mutex_);
|
||||
advs_.erase(adv_it);
|
||||
}
|
||||
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_,
|
||||
"RegisterAdvertisement", *error);
|
||||
auto name = error->getName();
|
||||
std::string msg = error->getMessage();
|
||||
absl::Status status;
|
||||
|
||||
if (name == "org.bluez.Error.InvalidArguments" ||
|
||||
name == "org.bluez.Error.InvalidLength") {
|
||||
status = absl::InvalidArgumentError(msg);
|
||||
} else if (name == "org.bluez.Error.AlreadyExists") {
|
||||
status = absl::AlreadyExistsError(msg);
|
||||
} else if (name == "org.bluez.Error.NotPermitted") {
|
||||
status = absl::ResourceExhaustedError(msg);
|
||||
} else {
|
||||
status = absl::UnknownError(msg);
|
||||
}
|
||||
shared_cb->start_advertising_result(std::move(status));
|
||||
} else {
|
||||
shared_cb->start_advertising_result(absl::OkStatus());
|
||||
}
|
||||
});
|
||||
|
||||
absl::AnyInvocable<absl::Status()> stop_adv = [&, adv_it]() {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Unregistering advertisement object "
|
||||
<< (*adv_it)->getObjectPath();
|
||||
absl::MutexLock lock(&advs_mutex_);
|
||||
try {
|
||||
adv_manager_->UnregisterAdvertisement((*adv_it)->getObjectPath());
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisement", e);
|
||||
return absl::UnknownError(e.getMessage());
|
||||
}
|
||||
advs_.erase(adv_it);
|
||||
return absl::OkStatus();
|
||||
};
|
||||
|
||||
return std::make_unique<api::ble_v2::BleMedium::AdvertisingSession>(
|
||||
api::ble_v2::BleMedium::AdvertisingSession{std::move(stop_adv)});
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattServer> BleV2Medium::StartGattServer(
|
||||
api::ble_v2::ServerGattConnectionCallback callback) {
|
||||
return std::make_unique<GattServer>(system_bus_, adapter_, devices_,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
bool BleV2Medium::StartLEDiscovery() {
|
||||
std::map<std::string, sdbus::Variant> filter;
|
||||
filter["Transport"] = "le";
|
||||
auto &adapter = adapter_.GetBluezAdapterObject();
|
||||
|
||||
try {
|
||||
adapter.SetDiscoveryFilter(filter);
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "SetDiscoveryFilter", e);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Starting LE discovery on "
|
||||
<< adapter.getObjectPath();
|
||||
adapter.StartDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2Medium::StartScanning(const Uuid &service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) {
|
||||
if (cur_monitored_service_uuid_.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": A sync scanning session is already active for "
|
||||
<< std::string{*cur_monitored_service_uuid_};
|
||||
return false;
|
||||
}
|
||||
|
||||
if (adv_monitor_manager_ == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": Advertising monitor not supported by BlueZ";
|
||||
// TODO: Implement manual monitoring.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MonitorManagerSupportsOr()) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< __func__
|
||||
<< ": \"or_patterns\" not supported by AdvertisementMonitorManager";
|
||||
// TODO: Implement manual monitoring.
|
||||
return false;
|
||||
}
|
||||
|
||||
absl::MutexLock lock(&active_adv_monitors_mutex_);
|
||||
if (active_adv_monitors_.count(service_uuid) == 1) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": an advertising session for service "
|
||||
<< std::string{service_uuid} << " already exists";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto monitor = std::make_unique<bluez::AdvertisementMonitor>(
|
||||
system_bus_, service_uuid, tx_power_level, "or_patterns", devices_,
|
||||
std::move(callback));
|
||||
try {
|
||||
monitor->emitInterfacesAddedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesAdded signal for object path "
|
||||
<< monitor->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!StartLEDiscovery()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Could not start LE discovery on adapter "
|
||||
<< adapter_.GetObjectPath();
|
||||
try {
|
||||
monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesRemoved signal for object path "
|
||||
<< monitor->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
active_adv_monitors_[service_uuid] = std::move(monitor);
|
||||
cur_monitored_service_uuid_ = service_uuid;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2Medium::StopScanning() {
|
||||
if (!cur_monitored_service_uuid_.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": No sync scanning session is currently active.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (adv_monitor_manager_ == nullptr) {
|
||||
// TODO: Implement manual monitoring.
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &adapter = adapter_.GetBluezAdapterObject();
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Stopping discovery for adapter "
|
||||
<< adapter.getObjectPath();
|
||||
try {
|
||||
adapter.StopDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e);
|
||||
}
|
||||
|
||||
absl::MutexLock lock(&active_adv_monitors_mutex_);
|
||||
auto monitor_it = active_adv_monitors_.find(*cur_monitored_service_uuid_);
|
||||
assert(monitor_it != active_adv_monitors_.end());
|
||||
|
||||
auto &[_uuid, adv_monitor] = *monitor_it;
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Removing advertising monitor "
|
||||
<< adv_monitor->getObjectPath();
|
||||
adv_monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
active_adv_monitors_.erase(monitor_it);
|
||||
cur_monitored_service_uuid_ = std::nullopt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleMedium::ScanningSession>
|
||||
BleV2Medium::StartScanning(const Uuid &service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanningCallback callback) {
|
||||
if (adv_monitor_manager_ == nullptr) {
|
||||
// TODO: Implement manual monitoring.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
absl::MutexLock lock(&active_adv_monitors_mutex_);
|
||||
if (active_adv_monitors_.count(service_uuid) == 1) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Service " << std::string{service_uuid}
|
||||
<< " is already being advertised";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto monitor = std::make_unique<bluez::AdvertisementMonitor>(
|
||||
system_bus_, service_uuid, tx_power_level, "or_patterns", devices_,
|
||||
std::move(callback));
|
||||
try {
|
||||
monitor->emitInterfacesAddedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesAdded signal for object path "
|
||||
<< monitor->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!StartLEDiscovery()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Could not start LE discovery on adapter "
|
||||
<< adapter_.GetObjectPath();
|
||||
try {
|
||||
monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesRemoved signal for object path "
|
||||
<< monitor->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
active_adv_monitors_[service_uuid] = std::move(monitor);
|
||||
return std::make_unique<ScanningSession>(
|
||||
ScanningSession{.stop_scanning = [this, service_uuid]() {
|
||||
absl::MutexLock lock(&active_adv_monitors_mutex_);
|
||||
if (active_adv_monitors_.count(service_uuid) == 0) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Advertising monitor for service "
|
||||
<< std::string{service_uuid} << " does not exist anymore";
|
||||
return absl::NotFoundError(
|
||||
"Advertising monitor for this service does not exist");
|
||||
}
|
||||
|
||||
auto &monitor = active_adv_monitors_[service_uuid];
|
||||
try {
|
||||
monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesRemoved signal for object path "
|
||||
<< monitor->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
}
|
||||
|
||||
active_adv_monitors_.erase(service_uuid);
|
||||
|
||||
auto &adapter = adapter_.GetBluezAdapterObject();
|
||||
try {
|
||||
adapter.StopDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e);
|
||||
return absl::InternalError(e.getMessage());
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}});
|
||||
}
|
||||
|
||||
bool BleV2Medium::GetRemotePeripheral(const std::string &mac_address,
|
||||
GetRemotePeripheralCallback callback) {
|
||||
auto device = devices_->get_device_by_address(mac_address);
|
||||
if (device == nullptr) return false;
|
||||
callback(*device);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2Medium::GetRemotePeripheral(api::ble_v2::BlePeripheral::UniqueId id,
|
||||
GetRemotePeripheralCallback callback) {
|
||||
auto device = devices_->get_device_by_unique_id(id);
|
||||
if (device == nullptr) return false;
|
||||
callback(*device);
|
||||
return true;
|
||||
}
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
@@ -15,41 +15,57 @@
|
||||
#ifndef PLATFORM_IMPL_LINUX_API_BLE_V2_MEDIUM_H_
|
||||
#define PLATFORM_IMPL_LINUX_API_BLE_V2_MEDIUM_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/ble_v2_server_socket.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_devices.h"
|
||||
#include "internal/platform/implementation/linux/bluez_advertisement_monitor.h"
|
||||
#include "internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h"
|
||||
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
class BleV2Medium final : public api::ble_v2::BleMedium {
|
||||
public:
|
||||
BleV2Medium(const BleV2Medium &) = delete;
|
||||
BleV2Medium(BleV2Medium &&) = delete;
|
||||
BleV2Medium &operator=(const BleV2Medium &) = delete;
|
||||
BleV2Medium &operator=(BleV2Medium &&) = delete;
|
||||
|
||||
BleV2Medium(sdbus::IConnection &system_bus ABSL_ATTRIBUTE_LIFETIME_BOUND,
|
||||
BluetoothAdapter &adapter);
|
||||
~BleV2Medium() override = default;
|
||||
|
||||
bool StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData &advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters) override {
|
||||
return false;
|
||||
}
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters) override
|
||||
ABSL_LOCKS_EXCLUDED(cur_adv_mutex_);
|
||||
std::unique_ptr<AdvertisingSession> StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData &advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters,
|
||||
AdvertisingCallback callback) override {
|
||||
return nullptr;
|
||||
}
|
||||
bool StopAdvertising() override { return false; }
|
||||
AdvertisingCallback callback) ABSL_LOCKS_EXCLUDED(advs_mutex_) override;
|
||||
bool StopAdvertising() override ABSL_LOCKS_EXCLUDED(advs_mutex_);
|
||||
|
||||
bool StartScanning(const Uuid &service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) override {
|
||||
return false;
|
||||
}
|
||||
bool StopScanning() override { return false; }
|
||||
ScanCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(active_adv_monitors_mutex_);
|
||||
bool StopScanning() override ABSL_LOCKS_EXCLUDED(active_adv_monitors_mutex_);
|
||||
|
||||
std::unique_ptr<ScanningSession> StartScanning(
|
||||
const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanningCallback callback) override {
|
||||
return nullptr;
|
||||
};
|
||||
ScanningCallback callback) override;
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattServer> StartGattServer(
|
||||
api::ble_v2::ServerGattConnectionCallback callback) override {
|
||||
return nullptr;
|
||||
}
|
||||
api::ble_v2::ServerGattConnectionCallback callback) override;
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattClient> ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral &peripheral,
|
||||
@@ -60,7 +76,7 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleServerSocket> OpenServerSocket(
|
||||
const std::string &service_id) override {
|
||||
return nullptr;
|
||||
return std::make_unique<BleV2ServerSocket>();
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleSocket> Connect(
|
||||
@@ -71,13 +87,53 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
}
|
||||
bool IsExtendedAdvertisementsAvailable() override { return false; }
|
||||
bool GetRemotePeripheral(const std::string &mac_address,
|
||||
GetRemotePeripheralCallback callback) override {
|
||||
return false;
|
||||
}
|
||||
GetRemotePeripheralCallback callback) override;
|
||||
bool GetRemotePeripheral(api::ble_v2::BlePeripheral::UniqueId id,
|
||||
GetRemotePeripheralCallback callback) override {
|
||||
return false;
|
||||
GetRemotePeripheralCallback callback) override;
|
||||
|
||||
private:
|
||||
bool StartLEDiscovery();
|
||||
|
||||
bool MonitorManagerSupportsOr() {
|
||||
std::vector<std::string> supported_types;
|
||||
try {
|
||||
supported_types = adv_monitor_manager_->SupportedMonitorTypes();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(adv_monitor_manager_, "SupportedMonitorTypes",
|
||||
e);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto is_supported_type = [](std::string pattern) {
|
||||
return pattern == "or_patterns";
|
||||
};
|
||||
|
||||
auto end = supported_types.cend();
|
||||
return std::find_if(supported_types.cbegin(), end, is_supported_type) !=
|
||||
end;
|
||||
}
|
||||
|
||||
sdbus::IConnection &system_bus_;
|
||||
BluetoothAdapter adapter_;
|
||||
ObserverList<api::BluetoothClassicMedium::Observer> observers_ = {};
|
||||
std::shared_ptr<BluetoothDevices> devices_;
|
||||
|
||||
std::unique_ptr<bluez::AdvertisementMonitorManager> adv_monitor_manager_;
|
||||
absl::Mutex active_adv_monitors_mutex_;
|
||||
absl::flat_hash_map<Uuid, std::unique_ptr<bluez::AdvertisementMonitor>>
|
||||
active_adv_monitors_ ABSL_GUARDED_BY(active_adv_monitors_mutex_);
|
||||
// Used by the synchronous variant of StartScanning
|
||||
std::optional<Uuid> cur_monitored_service_uuid_;
|
||||
|
||||
std::unique_ptr<bluez::LEAdvertisementManager> adv_manager_;
|
||||
|
||||
absl::Mutex cur_adv_mutex_;
|
||||
std::unique_ptr<bluez::LEAdvertisement> cur_adv_
|
||||
ABSL_GUARDED_BY(cur_adv_mutex_);
|
||||
|
||||
absl::Mutex advs_mutex_;
|
||||
std::list<std::unique_ptr<bluez::LEAdvertisement>> advs_
|
||||
ABSL_GUARDED_BY(advs_mutex_);
|
||||
};
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_API_BLE_V2_SERVER_SOCKET_H_
|
||||
#define PLATFORM_IMPL_LINUX_API_BLE_V2_SERVER_SOCKET_H_
|
||||
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
class BleV2ServerSocket final : public api::ble_v2::BleServerSocket {
|
||||
public:
|
||||
std::unique_ptr<api::ble_v2::BleSocket> Accept() override {
|
||||
stopped_.WaitForNotification();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Exception Close() override {
|
||||
if (stopped_.HasBeenNotified()) return {Exception::kIo};
|
||||
stopped_.Notify();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
private:
|
||||
absl::Notification stopped_;
|
||||
};
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "internal/platform/implementation/linux/bluez_advertisement_monitor.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/utils.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
AdvertisementMonitor::AdvertisementMonitor(
|
||||
sdbus::IConnection &system_bus, Uuid service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level, absl::string_view type,
|
||||
std::shared_ptr<BluetoothDevices> devices,
|
||||
api::ble_v2::BleMedium::ScanCallback scan_callback)
|
||||
: AdvertisementMonitor(
|
||||
system_bus, service_uuid, tx_power_level, type, std::move(devices),
|
||||
api::ble_v2::BleMedium::ScanningCallback{
|
||||
.start_scanning_result = nullptr,
|
||||
.advertisement_found_cb =
|
||||
std::move(scan_callback.advertisement_found_cb)}) {}
|
||||
|
||||
AdvertisementMonitor::AdvertisementMonitor(
|
||||
sdbus::IConnection &system_bus, Uuid service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level, absl::string_view type,
|
||||
std::shared_ptr<BluetoothDevices> devices,
|
||||
api::ble_v2::BleMedium::ScanningCallback scan_callback)
|
||||
: AdaptorInterfaces(system_bus, bluez::advertisement_monitor_path(
|
||||
std::string{service_uuid})),
|
||||
devices_(std::move(devices)),
|
||||
scan_callback_{std::move(scan_callback.advertisement_found_cb)},
|
||||
start_scanning_result_callback_(
|
||||
std::move(scan_callback.start_scanning_result)),
|
||||
type_(type),
|
||||
service_uuid_(service_uuid),
|
||||
tx_power_level_(tx_power_level) {
|
||||
registerAdaptor();
|
||||
}
|
||||
|
||||
void AdvertisementMonitor::DeviceFound(const sdbus::ObjectPath &device) {
|
||||
devices_->cleanup_lost_peripherals();
|
||||
auto peripheral = devices_->add_new_device(device);
|
||||
std::map<std::string, sdbus::Variant> service_data;
|
||||
try {
|
||||
service_data = peripheral->ServiceData();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(peripheral, "ServiceData", e);
|
||||
return;
|
||||
}
|
||||
|
||||
struct api::ble_v2::BleAdvertisementData adv_data;
|
||||
for (const auto &[uuid_str, data] : service_data) {
|
||||
auto uuid = UuidFromString(uuid_str);
|
||||
if (!uuid.has_value()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Could not parse UUID string in ServiceData for peripheral "
|
||||
<< peripheral->getObjectPath();
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> bytes = data;
|
||||
adv_data.service_data.emplace(*uuid,
|
||||
std::string(bytes.begin(), bytes.end()));
|
||||
}
|
||||
scan_callback_.advertisement_found_cb(*peripheral, adv_data);
|
||||
}
|
||||
|
||||
void AdvertisementMonitor::DeviceLost(const sdbus::ObjectPath &device) {
|
||||
devices_->mark_peripheral_lost(device);
|
||||
}
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_H_
|
||||
#define PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_H_
|
||||
#include <sdbus-c++/AdaptorInterfaces.h>
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/StandardInterfaces.h>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_devices.h"
|
||||
#include "internal/platform/implementation/linux/bluez.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/advertisement_monitor_server.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
class AdvertisementMonitor final
|
||||
: public sdbus::AdaptorInterfaces<org::bluez::AdvertisementMonitor1_adaptor,
|
||||
sdbus::ManagedObject_adaptor> {
|
||||
public:
|
||||
AdvertisementMonitor(const AdvertisementMonitor&) = delete;
|
||||
AdvertisementMonitor(AdvertisementMonitor&&) = delete;
|
||||
AdvertisementMonitor& operator=(const AdvertisementMonitor&) = delete;
|
||||
AdvertisementMonitor& operator=(AdvertisementMonitor&&) = delete;
|
||||
|
||||
AdvertisementMonitor(sdbus::IConnection& system_bus, Uuid service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
absl::string_view type,
|
||||
std::shared_ptr<BluetoothDevices> devices,
|
||||
api::ble_v2::BleMedium::ScanCallback scan_callback);
|
||||
AdvertisementMonitor(sdbus::IConnection& system_bus, Uuid service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
absl::string_view type,
|
||||
std::shared_ptr<BluetoothDevices> devices,
|
||||
api::ble_v2::BleMedium::ScanningCallback scan_callback);
|
||||
~AdvertisementMonitor() { unregisterAdaptor(); }
|
||||
|
||||
private:
|
||||
// Methods
|
||||
void Release() override {}
|
||||
void Activate() override {
|
||||
if (start_scanning_result_callback_ != nullptr) {
|
||||
start_scanning_result_callback_(absl::OkStatus());
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceFound(const sdbus::ObjectPath& device) override;
|
||||
void DeviceLost(const sdbus::ObjectPath& device) override;
|
||||
|
||||
// Properties
|
||||
std::string Type() override { return type_; };
|
||||
int16_t RSSILowThreshold() override { return 0; };
|
||||
int16_t RSSIHighThreshold() override {
|
||||
return bluez::TxPowerLevelDbm(tx_power_level_);
|
||||
}
|
||||
uint16_t RSSISamplingPeriod() override {
|
||||
// The Windows implementation uses a sampling interval of 2 seconds.
|
||||
return 20;
|
||||
}
|
||||
std::vector<sdbus::Struct<uint8_t, uint8_t, std::vector<uint8_t>>> Patterns()
|
||||
override {
|
||||
std::array<char, 16> service_id_data = service_uuid_.data();
|
||||
return {{0,
|
||||
0x16,
|
||||
{static_cast<uint8_t>(service_id_data[3] & 0xFF),
|
||||
static_cast<uint8_t>(service_id_data[2] & 0xFF)}}};
|
||||
};
|
||||
|
||||
std::shared_ptr<BluetoothDevices> devices_;
|
||||
api::ble_v2::BleMedium::ScanCallback scan_callback_;
|
||||
absl::AnyInvocable<void(absl::Status)> start_scanning_result_callback_;
|
||||
|
||||
std::string type_;
|
||||
Uuid service_uuid_;
|
||||
api::ble_v2::TxPowerLevel tx_power_level_;
|
||||
};
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_MANAGER_H_
|
||||
#define PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_MANAGER_H_
|
||||
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/ProxyInterfaces.h>
|
||||
|
||||
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/linux/bluez.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/advertisement_monitor_manager_client.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
class AdvertisementMonitorManager final
|
||||
: public sdbus::ProxyInterfaces<
|
||||
org::bluez::AdvertisementMonitorManager1_proxy> {
|
||||
private:
|
||||
friend std::unique_ptr<AdvertisementMonitorManager>
|
||||
std::make_unique<AdvertisementMonitorManager>(sdbus::IConnection &,
|
||||
const BluetoothAdapter &);
|
||||
AdvertisementMonitorManager(sdbus::IConnection &system_bus,
|
||||
const BluetoothAdapter &adapter)
|
||||
: ProxyInterfaces(system_bus, "org.bluez", adapter.GetObjectPath()) {
|
||||
registerProxy();
|
||||
}
|
||||
|
||||
public:
|
||||
AdvertisementMonitorManager(const AdvertisementMonitorManager &) = delete;
|
||||
AdvertisementMonitorManager(AdvertisementMonitorManager &&) = delete;
|
||||
AdvertisementMonitorManager &operator=(const AdvertisementMonitorManager &) =
|
||||
delete;
|
||||
AdvertisementMonitorManager &operator=(AdvertisementMonitorManager &&) =
|
||||
delete;
|
||||
~AdvertisementMonitorManager() { unregisterProxy(); }
|
||||
|
||||
static std::unique_ptr<AdvertisementMonitorManager>
|
||||
DiscoverAdvertisementMonitorManager(sdbus::IConnection &system_bus,
|
||||
const BluetoothAdapter &adapter) {
|
||||
bluez::BluezObjectManager manager(system_bus);
|
||||
std::map<sdbus::ObjectPath,
|
||||
std::map<std::string, std::map<std::string, sdbus::Variant>>>
|
||||
objects;
|
||||
try {
|
||||
objects = manager.GetManagedObjects();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&manager, "GetManagedObjects", e);
|
||||
return nullptr;
|
||||
}
|
||||
if (objects.count(adapter.GetObjectPath()) == 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Adapter object no longer exists "
|
||||
<< adapter.GetObjectPath();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (objects[adapter.GetObjectPath()].count(
|
||||
org::bluez::AdvertisementMonitorManager1_proxy::INTERFACE_NAME) ==
|
||||
0) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Adapter " << adapter.GetObjectPath()
|
||||
<< " doesn't provide "
|
||||
<< org::bluez::AdvertisementMonitorManager1_proxy::INTERFACE_NAME;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<AdvertisementMonitorManager>(system_bus, adapter);
|
||||
}
|
||||
};
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,231 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sdbus-c++/Error.h>
|
||||
#include <sdbus-c++/MethodResult.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_characteristic.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
void GattCharacteristic::Update(const nearby::ByteArray &value) {
|
||||
std::vector<uint8_t> bytes(value.size());
|
||||
const auto *buf = value.data();
|
||||
for (auto i = 0; i < value.size(); i++) bytes[i] = buf[i];
|
||||
|
||||
absl::MutexLock static_value_lock(&static_value_mutex_);
|
||||
static_value_ = std::move(bytes);
|
||||
}
|
||||
|
||||
absl::Status GattCharacteristic::NotifyChanged(bool confirm,
|
||||
const ByteArray &new_value) {
|
||||
std::vector<uint8_t> bytes(new_value.size());
|
||||
const auto *buf = new_value.data();
|
||||
for (auto i = 0; i < new_value.size(); i++) bytes[i] = buf[i];
|
||||
|
||||
{
|
||||
absl::MutexLock lock(&cached_value_mutex_);
|
||||
cached_value_ = bytes;
|
||||
}
|
||||
|
||||
if (confirm) {
|
||||
auto confirmed = [&]() {
|
||||
confirmed_mutex_.AssertReaderHeld();
|
||||
return confirmed_;
|
||||
};
|
||||
{
|
||||
absl::MutexLock lock(&confirmed_mutex_);
|
||||
confirmed_ = false;
|
||||
}
|
||||
absl::ReaderMutexLock lock(&confirmed_mutex_, absl::Condition(&confirmed));
|
||||
}
|
||||
|
||||
try {
|
||||
emitPropertiesChangedSignal(GattCharacteristic1_adaptor::INTERFACE_NAME,
|
||||
{"Value"});
|
||||
return absl::OkStatus();
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Error emitting PropertiesChanged signal on "
|
||||
<< getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
return absl::UnknownError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void GattCharacteristic::ReadValue(
|
||||
sdbus::Result<std::vector<uint8_t>> &&result,
|
||||
std::map<std::string, sdbus::Variant> options) {
|
||||
{
|
||||
absl::ReaderMutexLock static_value_lock(&static_value_mutex_);
|
||||
if (static_value_.has_value()) {
|
||||
result.returnResults(*static_value_);
|
||||
|
||||
absl::MutexLock cached_value_lock(&cached_value_mutex_);
|
||||
cached_value_ = *static_value_;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t offset = options["offset"];
|
||||
sdbus::ObjectPath device_path = options["device"];
|
||||
|
||||
auto device = devices_->get_device_by_path(device_path);
|
||||
if (device == nullptr) {
|
||||
result.returnError(
|
||||
sdbus::Error("org.bluez.Error.NotAuthorized", "device does not exist"));
|
||||
return;
|
||||
}
|
||||
auto characteristic = characteristic_;
|
||||
server_cb_->on_characteristic_read_cb(
|
||||
*device, characteristic, static_cast<int>(offset),
|
||||
[result = std::move(result),
|
||||
this](absl::StatusOr<absl::string_view> data) {
|
||||
const auto &status = data.status();
|
||||
if (status.ok()) {
|
||||
auto str = data.value();
|
||||
std::vector<uint8_t> bytes(str.size());
|
||||
for (auto i = 0; i < str.size(); i++) {
|
||||
bytes[i] = str[i];
|
||||
}
|
||||
result.returnResults(bytes);
|
||||
|
||||
absl::MutexLock lock(&cached_value_mutex_);
|
||||
cached_value_ = bytes;
|
||||
} else if (absl::IsPermissionDenied(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.NotPermitted",
|
||||
std::string(status.message())));
|
||||
} else if (absl::IsUnauthenticated(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.NotAuthorized",
|
||||
std::string(status.message())));
|
||||
} else if (absl::IsOutOfRange(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.InvalidOffset",
|
||||
std::string(status.message())));
|
||||
} else if (absl::IsUnimplemented(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.NotSupported",
|
||||
std::string(status.message())));
|
||||
} else {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.Failed",
|
||||
std::string(status.message())));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void GattCharacteristic::WriteValue(
|
||||
sdbus::Result<> &&result, std::vector<uint8_t> value,
|
||||
std::map<std::string, sdbus::Variant> options) {
|
||||
uint16_t offset = options["offset"];
|
||||
sdbus::ObjectPath device_path = options["device"];
|
||||
|
||||
auto device = devices_->get_device_by_path(device_path);
|
||||
if (device == nullptr) {
|
||||
result.returnError(
|
||||
sdbus::Error("org.bluez.Error.NotAuthorized", "device does not exist"));
|
||||
return;
|
||||
}
|
||||
std::string type = options["type"];
|
||||
|
||||
std::string data(value.begin(), value.end());
|
||||
auto characteristic = characteristic_;
|
||||
|
||||
if (type != "command") {
|
||||
server_cb_->on_characteristic_write_cb(
|
||||
*device, characteristic, static_cast<int>(offset), data,
|
||||
[result = std::move(result)](absl::Status status) {
|
||||
if (status.ok()) {
|
||||
result.returnResults();
|
||||
} else if (absl::IsPermissionDenied(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.NotPermitted",
|
||||
std::string(status.message())));
|
||||
} else if (absl::IsUnauthenticated(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.NotAuthorized",
|
||||
std::string(status.message())));
|
||||
} else if (absl::IsOutOfRange(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.InvalidOffset",
|
||||
std::string(status.message())));
|
||||
} else if (absl::IsUnimplemented(status)) {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.NotSupported",
|
||||
std::string(status.message())));
|
||||
} else {
|
||||
result.returnError(sdbus::Error("org.bluez.Error.Failed",
|
||||
std::string(status.message())));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.returnResults();
|
||||
}
|
||||
}
|
||||
|
||||
void GattCharacteristic::StartNotify() {
|
||||
if ((characteristic_.property |
|
||||
api::ble_v2::GattCharacteristic::Property::kNotify) ==
|
||||
api::ble_v2::GattCharacteristic::Property::kNotify) {
|
||||
server_cb_->characteristic_subscription_cb(characteristic_);
|
||||
notifying_ = true;
|
||||
} else {
|
||||
throw(sdbus::Error("org.bluez.Error.NotSupported"));
|
||||
}
|
||||
}
|
||||
|
||||
void GattCharacteristic::StopNotify() {
|
||||
if ((characteristic_.property |
|
||||
api::ble_v2::GattCharacteristic::Property::kNotify) ==
|
||||
api::ble_v2::GattCharacteristic::Property::kNotify) {
|
||||
server_cb_->characteristic_unsubscription_cb(characteristic_);
|
||||
notifying_ = false;
|
||||
} else {
|
||||
throw(sdbus::Error("org.bluez.Error.Failed"));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> GattCharacteristic::Flags() {
|
||||
auto characteristic = characteristic_;
|
||||
std::vector<std::string> flags;
|
||||
|
||||
if ((characteristic.permission &
|
||||
api::ble_v2::GattCharacteristic::Permission::kRead) ==
|
||||
api::ble_v2::GattCharacteristic::Permission::kRead ||
|
||||
(characteristic.property &
|
||||
api::ble_v2::GattCharacteristic::Property::kRead) ==
|
||||
api::ble_v2::GattCharacteristic::Property::kRead)
|
||||
flags.push_back("read");
|
||||
|
||||
if ((characteristic.permission &
|
||||
api::ble_v2::GattCharacteristic::Permission::kWrite) ==
|
||||
api::ble_v2::GattCharacteristic::Permission::kWrite ||
|
||||
(characteristic.property &
|
||||
api::ble_v2::GattCharacteristic::Property::kWrite) ==
|
||||
api::ble_v2::GattCharacteristic::Property::kWrite)
|
||||
flags.push_back("write");
|
||||
|
||||
if ((characteristic.property &
|
||||
api::ble_v2::GattCharacteristic::Property::kIndicate) ==
|
||||
api::ble_v2::GattCharacteristic::Property::kIndicate)
|
||||
flags.push_back("indicate");
|
||||
|
||||
if ((characteristic.property &
|
||||
api::ble_v2::GattCharacteristic::Property::kNotify) ==
|
||||
api::ble_v2::GattCharacteristic::Property::kNotify)
|
||||
flags.push_back("notify");
|
||||
|
||||
return flags;
|
||||
}
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,125 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_GATT_CHARACTERISTIC_H_
|
||||
#define PLATFORM_IMPL_LINUX_BLUEZ_GATT_CHARACTERISTIC_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <sdbus-c++/AdaptorInterfaces.h>
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/MethodResult.h>
|
||||
#include <sdbus-c++/StandardInterfaces.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_devices.h"
|
||||
#include "internal/platform/implementation/linux/bluez.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_server.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
class GattCharacteristic final
|
||||
: public sdbus::AdaptorInterfaces<org::bluez::GattCharacteristic1_adaptor,
|
||||
sdbus::Properties_adaptor,
|
||||
sdbus::ManagedObject_adaptor> {
|
||||
public:
|
||||
GattCharacteristic(const GattCharacteristic &) = delete;
|
||||
GattCharacteristic(GattCharacteristic &&) = delete;
|
||||
GattCharacteristic &operator=(const GattCharacteristic &) = delete;
|
||||
GattCharacteristic &operator=(GattCharacteristic &&) = delete;
|
||||
|
||||
GattCharacteristic(
|
||||
sdbus::IConnection &system_bus,
|
||||
const sdbus::ObjectPath &service_object_path, size_t num,
|
||||
const api::ble_v2::GattCharacteristic &characteristic,
|
||||
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb,
|
||||
std::shared_ptr<BluetoothDevices> devices)
|
||||
: AdaptorInterfaces(system_bus, bluez::gatt_characteristic_path(
|
||||
service_object_path, num)),
|
||||
devices_(std::move(devices)),
|
||||
server_cb_(std::move(server_cb)),
|
||||
characteristic_(characteristic),
|
||||
service_object_path_(service_object_path),
|
||||
notifying_(false),
|
||||
confirmed_(false) {
|
||||
registerAdaptor();
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< __func__ << "Creating a "
|
||||
<< org::bluez::GattCharacteristic1_adaptor::INTERFACE_NAME
|
||||
<< " object at " << getObjectPath();
|
||||
}
|
||||
~GattCharacteristic() { unregisterAdaptor(); }
|
||||
|
||||
void Update(const nearby::ByteArray &value)
|
||||
ABSL_LOCKS_EXCLUDED(static_value_mutex_);
|
||||
absl::Status NotifyChanged(bool confirm, const ByteArray &new_value)
|
||||
ABSL_LOCKS_EXCLUDED(confirmed_mutex_);
|
||||
|
||||
private:
|
||||
// Methods
|
||||
void ReadValue(sdbus::Result<std::vector<uint8_t>> &&result,
|
||||
std::map<std::string, sdbus::Variant> options) override
|
||||
ABSL_LOCKS_EXCLUDED(cached_value_mutex_, static_value_mutex_);
|
||||
void WriteValue(sdbus::Result<> &&result, std::vector<uint8_t> value,
|
||||
std::map<std::string, sdbus::Variant> options) override;
|
||||
void StartNotify() override;
|
||||
void StopNotify() override;
|
||||
void Confirm() override ABSL_LOCKS_EXCLUDED(confirmed_mutex_) {
|
||||
absl::MutexLock lock(&confirmed_mutex_);
|
||||
confirmed_ = true;
|
||||
};
|
||||
|
||||
// Properties
|
||||
std::string UUID() override { return std::string{characteristic_.uuid}; }
|
||||
sdbus::ObjectPath Service() override { return service_object_path_; }
|
||||
bool Notifying() override { return notifying_; }
|
||||
std::vector<std::string> Flags() override;
|
||||
std::vector<uint8_t> Value() override
|
||||
ABSL_LOCKS_EXCLUDED(cached_value_mutex_) {
|
||||
absl::ReaderMutexLock lock(&cached_value_mutex_);
|
||||
return cached_value_;
|
||||
}
|
||||
|
||||
std::shared_ptr<BluetoothDevices> devices_;
|
||||
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb_;
|
||||
api::ble_v2::GattCharacteristic characteristic_;
|
||||
|
||||
// Set by `GattServer::UpdateCharacteristic()`
|
||||
absl::Mutex static_value_mutex_;
|
||||
std::optional<std::vector<uint8_t>> static_value_
|
||||
ABSL_GUARDED_BY(static_value_mutex_);
|
||||
|
||||
sdbus::ObjectPath service_object_path_;
|
||||
std::atomic_bool notifying_;
|
||||
absl::Mutex cached_value_mutex_;
|
||||
std::vector<uint8_t> cached_value_ ABSL_GUARDED_BY(cached_value_mutex_);
|
||||
|
||||
absl::Mutex confirmed_mutex_;
|
||||
bool confirmed_;
|
||||
};
|
||||
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_
|
||||
#define PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/ProxyInterfaces.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_manager_client.h"
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
class GattManager
|
||||
: public sdbus::ProxyInterfaces<org::bluez::GattManager1_proxy> {
|
||||
public:
|
||||
GattManager(const GattManager &) = delete;
|
||||
GattManager(GattManager &&) = delete;
|
||||
GattManager &operator=(const GattManager &) = delete;
|
||||
GattManager &operator=(GattManager &&) = delete;
|
||||
|
||||
GattManager(sdbus::IConnection &system_bus,
|
||||
sdbus::ObjectPath adapter_object_path)
|
||||
: ProxyInterfaces(system_bus, "org.bluez",
|
||||
std::move(adapter_object_path)) {
|
||||
registerProxy();
|
||||
}
|
||||
~GattManager() { unregisterProxy(); }
|
||||
};
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_service.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_characteristic.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_server.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
bool GattService::AddCharacteristic(
|
||||
const Uuid &service_uuid, const Uuid &characteristic_uuid,
|
||||
api::ble_v2::GattCharacteristic::Permission permission,
|
||||
api::ble_v2::GattCharacteristic::Property property) {
|
||||
absl::MutexLock lock(&characterstics_mutex_);
|
||||
api::ble_v2::GattCharacteristic characteristic{
|
||||
characteristic_uuid, service_uuid, permission, property};
|
||||
auto count = characteristics_.size();
|
||||
std::shared_ptr<GattCharacteristic> chr =
|
||||
std::make_shared<GattCharacteristic>(
|
||||
getObject().getConnection(), getObjectPath(), count, characteristic,
|
||||
server_cb_, devices_);
|
||||
try {
|
||||
chr->emitInterfacesAddedSignal(
|
||||
{org::bluez::GattCharacteristic1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesAdded signal for object path "
|
||||
<< chr->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
return false;
|
||||
}
|
||||
|
||||
characteristics_.insert({characteristic_uuid, std::move(chr)});
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<GattCharacteristic> GattService::GetCharacteristic(
|
||||
const Uuid &uuid) {
|
||||
absl::ReaderMutexLock lock(&characterstics_mutex_);
|
||||
if (characteristics_.count(uuid) == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return characteristics_[uuid];
|
||||
}
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,110 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_GATT_SERVICE_H_
|
||||
#define PLATFORM_IMPL_LINUX_BLUEZ_GATT_SERVICE_H_
|
||||
|
||||
#include <sdbus-c++/AdaptorInterfaces.h>
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/IObject.h>
|
||||
#include <sdbus-c++/StandardInterfaces.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluez.h"
|
||||
#include "internal/platform/implementation/linux/bluez_gatt_characteristic.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_server.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_service_server.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
class GattService final
|
||||
: public sdbus::AdaptorInterfaces<org::bluez::GattService1_adaptor,
|
||||
sdbus::ManagedObject_adaptor,
|
||||
sdbus::Properties_adaptor> {
|
||||
public:
|
||||
GattService(const GattService &) = delete;
|
||||
GattService(GattService &&) = delete;
|
||||
GattService &operator=(const GattService &) = delete;
|
||||
GattService &operator=(GattService &&) = delete;
|
||||
|
||||
GattService(
|
||||
sdbus::IConnection &system_bus, size_t num, const Uuid &service_uuid,
|
||||
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb,
|
||||
std::shared_ptr<BluetoothDevices> devices)
|
||||
: AdaptorInterfaces(system_bus, bluez::gatt_service_path(num)),
|
||||
devices_(std::move(devices)),
|
||||
server_cb_(std::move(server_cb)),
|
||||
uuid_(service_uuid),
|
||||
primary_(true) {
|
||||
registerAdaptor();
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Created a "
|
||||
<< org::bluez::GattService1_adaptor::INTERFACE_NAME
|
||||
<< " object at " << getObjectPath();
|
||||
}
|
||||
|
||||
~GattService() {
|
||||
absl::MutexLock lock(&characterstics_mutex_);
|
||||
for (auto &[_uuid, characteristic] : characteristics_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Removing characteristic "
|
||||
<< characteristic->getObjectPath();
|
||||
try {
|
||||
characteristic->emitInterfacesRemovedSignal(
|
||||
{org::bluez::GattCharacteristic1_adaptor::INTERFACE_NAME});
|
||||
} catch (const sdbus::Error &e) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": error emitting InterfacesRemoved signal for object path "
|
||||
<< characteristic->getObjectPath() << " with name '" << e.getName()
|
||||
<< "' and message '" << e.getMessage() << "'";
|
||||
}
|
||||
}
|
||||
unregisterAdaptor();
|
||||
}
|
||||
|
||||
bool AddCharacteristic(const Uuid &service_uuid,
|
||||
const Uuid &characteristic_uuid,
|
||||
api::ble_v2::GattCharacteristic::Permission permission,
|
||||
api::ble_v2::GattCharacteristic::Property property)
|
||||
ABSL_LOCKS_EXCLUDED(characterstics_mutex_);
|
||||
std::shared_ptr<GattCharacteristic> GetCharacteristic(const Uuid &uuid)
|
||||
ABSL_LOCKS_EXCLUDED(characterstics_mutex_);
|
||||
|
||||
private:
|
||||
// Properties
|
||||
std::string UUID() override { return uuid_; }
|
||||
bool Primary() override { return primary_; }
|
||||
sdbus::ObjectPath Device() override { return "/"; }
|
||||
std::vector<sdbus::ObjectPath> Includes() override { return {}; }
|
||||
|
||||
absl::Mutex characterstics_mutex_;
|
||||
absl::flat_hash_map<Uuid, std::shared_ptr<GattCharacteristic>>
|
||||
characteristics_ ABSL_GUARDED_BY(characterstics_mutex_);
|
||||
|
||||
std::shared_ptr<BluetoothDevices> devices_;
|
||||
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb_;
|
||||
|
||||
const std::string uuid_;
|
||||
const bool primary_;
|
||||
};
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluez.h"
|
||||
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
LEAdvertisement::LEAdvertisement(
|
||||
sdbus::IConnection& system_bus, sdbus::ObjectPath path,
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters)
|
||||
: AdaptorInterfaces(system_bus, std::move(path)),
|
||||
is_extended_advertisement_(advertising_data.is_extended_advertisement),
|
||||
advertise_set_parameters_(advertise_set_parameters) {
|
||||
for (const auto& [uuid, data] : advertising_data.service_data) {
|
||||
std::string uuid_string(uuid);
|
||||
std::vector<uint8_t> data_bytes(data.size());
|
||||
const auto* bytes = data.data();
|
||||
|
||||
service_uuids_.push_back(uuid_string);
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
data_bytes[i] = bytes[i];
|
||||
}
|
||||
|
||||
service_data_.insert({uuid_string, std::move(data_bytes)});
|
||||
}
|
||||
|
||||
registerAdaptor();
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Created a org.bluez.LEAdvertisement1 instance at "
|
||||
<< getObjectPath();
|
||||
}
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_LINUX_API_BLUEZ_BLE_ADVERTISEMENT_H_
|
||||
#define PLATFORM_IMPL_LINUX_API_BLUEZ_BLE_ADVERTISEMENT_H_
|
||||
|
||||
#include <sdbus-c++/AdaptorInterfaces.h>
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/ProxyInterfaces.h>
|
||||
#include <sdbus-c++/StandardInterfaces.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/linux/bluez.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/le_advertisement_manager_client.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/le_advertisement_server.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
namespace bluez {
|
||||
class LEAdvertisement final
|
||||
: public sdbus::AdaptorInterfaces<org::bluez::LEAdvertisement1_adaptor,
|
||||
sdbus::ObjectManager_adaptor> {
|
||||
public:
|
||||
LEAdvertisement(const LEAdvertisement&) = delete;
|
||||
LEAdvertisement(LEAdvertisement&&) = delete;
|
||||
LEAdvertisement& operator=(const LEAdvertisement&) = delete;
|
||||
LEAdvertisement& operator=(LEAdvertisement&&) = delete;
|
||||
|
||||
LEAdvertisement(sdbus::IConnection& system_bus, sdbus::ObjectPath path,
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters);
|
||||
|
||||
static std::unique_ptr<LEAdvertisement> CreateLEAdvertisement(
|
||||
sdbus::IConnection& system_bus,
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters) {
|
||||
static std::atomic<size_t> adv_count = 0;
|
||||
auto object_path = bluez::ble_advertisement_path(adv_count++);
|
||||
return std::make_unique<LEAdvertisement>(
|
||||
system_bus, object_path, advertising_data, advertising_parameters);
|
||||
}
|
||||
~LEAdvertisement() { unregisterAdaptor(); }
|
||||
|
||||
private:
|
||||
// Methods
|
||||
void Release() override {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": LE Advertisement released: " << getObjectPath();
|
||||
}
|
||||
|
||||
// Properties
|
||||
std::string Type() override { return "broadcast"; }
|
||||
std::vector<std::string> ServiceUUIDs() override { return {}; }
|
||||
std::map<std::string, sdbus::Variant> ManufacturerData() override {
|
||||
return {};
|
||||
}
|
||||
std::vector<std::string> SolicitUUIDs() override { return {}; }
|
||||
std::map<std::string, sdbus::Variant> ServiceData() override {
|
||||
return service_data_;
|
||||
}
|
||||
std::vector<std::string> Includes() override { return {}; }
|
||||
std::string LocalName() override { return {}; }
|
||||
uint16_t Duration() override { return 0; }
|
||||
uint16_t Timeout() override { return 0; }
|
||||
// Windows seems to hardcode the scan interval to 118.125 milliseconds, so
|
||||
// lets just replicate that.
|
||||
uint32_t MinInterval() override { return 118; }
|
||||
uint32_t MaxInterval() override { return 119; }
|
||||
int16_t TxPower() override {
|
||||
return bluez::TxPowerLevelDbm(advertise_set_parameters_.tx_power_level);
|
||||
};
|
||||
|
||||
bool is_extended_advertisement_;
|
||||
std::vector<std::string> service_uuids_;
|
||||
std::map<std::string, sdbus::Variant> service_data_;
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters_;
|
||||
};
|
||||
|
||||
class LEAdvertisementManager final
|
||||
: public sdbus::ProxyInterfaces<org::bluez::LEAdvertisingManager1_proxy> {
|
||||
public:
|
||||
LEAdvertisementManager(sdbus::IConnection& system_bus,
|
||||
BluetoothAdapter& adapter)
|
||||
: ProxyInterfaces(system_bus, "org.bluez", adapter.GetObjectPath()) {
|
||||
registerProxy();
|
||||
}
|
||||
~LEAdvertisementManager() { unregisterProxy(); }
|
||||
|
||||
LEAdvertisementManager(const LEAdvertisementManager&) = delete;
|
||||
LEAdvertisementManager(LEAdvertisementManager&&) = delete;
|
||||
LEAdvertisementManager& operator=(const LEAdvertisementManager&) = delete;
|
||||
LEAdvertisementManager& operator=(LEAdvertisementManager&&) = delete;
|
||||
};
|
||||
} // namespace bluez
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__advertisement_monitor_manager_client_h__proxy__H__
|
||||
#define __sdbuscpp__advertisement_monitor_manager_client_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class AdvertisementMonitorManager1_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.AdvertisementMonitorManager1";
|
||||
|
||||
protected:
|
||||
AdvertisementMonitorManager1_proxy(sdbus::IProxy& proxy)
|
||||
: proxy_(proxy)
|
||||
{
|
||||
}
|
||||
|
||||
~AdvertisementMonitorManager1_proxy() = default;
|
||||
|
||||
public:
|
||||
void RegisterMonitor(const sdbus::ObjectPath& application)
|
||||
{
|
||||
proxy_.callMethod("RegisterMonitor").onInterface(INTERFACE_NAME).withArguments(application);
|
||||
}
|
||||
|
||||
void UnregisterMonitor(const sdbus::ObjectPath& application)
|
||||
{
|
||||
proxy_.callMethod("UnregisterMonitor").onInterface(INTERFACE_NAME).withArguments(application);
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<std::string> SupportedMonitorTypes()
|
||||
{
|
||||
return proxy_.getProperty("SupportedMonitorTypes").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::vector<std::string> SupportedFeatures()
|
||||
{
|
||||
return proxy_.getProperty("SupportedFeatures").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IProxy& proxy_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__advertisement_monitor_server_h__adaptor__H__
|
||||
#define __sdbuscpp__advertisement_monitor_server_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class AdvertisementMonitor1_adaptor
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.AdvertisementMonitor1";
|
||||
|
||||
protected:
|
||||
AdvertisementMonitor1_adaptor(sdbus::IObject& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.registerMethod("Release").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Release(); });
|
||||
object_.registerMethod("Activate").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Activate(); });
|
||||
object_.registerMethod("DeviceFound").onInterface(INTERFACE_NAME).withInputParamNames("device").implementedAs([this](const sdbus::ObjectPath& device){ return this->DeviceFound(device); });
|
||||
object_.registerMethod("DeviceLost").onInterface(INTERFACE_NAME).withInputParamNames("device").implementedAs([this](const sdbus::ObjectPath& device){ return this->DeviceLost(device); });
|
||||
object_.registerProperty("Type").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Type(); });
|
||||
object_.registerProperty("RSSILowThreshold").onInterface(INTERFACE_NAME).withGetter([this](){ return this->RSSILowThreshold(); });
|
||||
object_.registerProperty("RSSIHighThreshold").onInterface(INTERFACE_NAME).withGetter([this](){ return this->RSSIHighThreshold(); });
|
||||
object_.registerProperty("RSSISamplingPeriod").onInterface(INTERFACE_NAME).withGetter([this](){ return this->RSSISamplingPeriod(); });
|
||||
object_.registerProperty("Patterns").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Patterns(); });
|
||||
}
|
||||
|
||||
~AdvertisementMonitor1_adaptor() = default;
|
||||
|
||||
private:
|
||||
virtual void Release() = 0;
|
||||
virtual void Activate() = 0;
|
||||
virtual void DeviceFound(const sdbus::ObjectPath& device) = 0;
|
||||
virtual void DeviceLost(const sdbus::ObjectPath& device) = 0;
|
||||
|
||||
private:
|
||||
virtual std::string Type() = 0;
|
||||
virtual int16_t RSSILowThreshold() = 0;
|
||||
virtual int16_t RSSIHighThreshold() = 0;
|
||||
virtual uint16_t RSSISamplingPeriod() = 0;
|
||||
virtual std::vector<sdbus::Struct<uint8_t, uint8_t, std::vector<uint8_t>>> Patterns() = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& object_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__generated_dbus_bluez_gatt_characteristic_client_h__proxy__H__
|
||||
#define __sdbuscpp__generated_dbus_bluez_gatt_characteristic_client_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class GattCharacteristic1_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.GattCharacteristic1";
|
||||
|
||||
protected:
|
||||
GattCharacteristic1_proxy(sdbus::IProxy& proxy)
|
||||
: proxy_(proxy)
|
||||
{
|
||||
}
|
||||
|
||||
~GattCharacteristic1_proxy() = default;
|
||||
|
||||
public:
|
||||
std::vector<uint8_t> ReadValue(const std::map<std::string, sdbus::Variant>& options)
|
||||
{
|
||||
std::vector<uint8_t> result;
|
||||
proxy_.callMethod("ReadValue").onInterface(INTERFACE_NAME).withArguments(options).storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteValue(const std::vector<uint8_t>& value, const std::map<std::string, sdbus::Variant>& options)
|
||||
{
|
||||
proxy_.callMethod("WriteValue").onInterface(INTERFACE_NAME).withArguments(value, options);
|
||||
}
|
||||
|
||||
void StartNotify()
|
||||
{
|
||||
proxy_.callMethod("StartNotify").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
void StopNotify()
|
||||
{
|
||||
proxy_.callMethod("StopNotify").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
void Confirm()
|
||||
{
|
||||
proxy_.callMethod("Confirm").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
public:
|
||||
std::string UUID()
|
||||
{
|
||||
return proxy_.getProperty("UUID").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath Service()
|
||||
{
|
||||
return proxy_.getProperty("Service").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Value()
|
||||
{
|
||||
return proxy_.getProperty("Value").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
bool Notifying()
|
||||
{
|
||||
return proxy_.getProperty("Notifying").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::vector<std::string> Flags()
|
||||
{
|
||||
return proxy_.getProperty("Flags").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IProxy& proxy_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__generated_dbus_bluez_gatt_characteristic_server_h__adaptor__H__
|
||||
#define __sdbuscpp__generated_dbus_bluez_gatt_characteristic_server_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class GattCharacteristic1_adaptor
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.GattCharacteristic1";
|
||||
|
||||
protected:
|
||||
GattCharacteristic1_adaptor(sdbus::IObject& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.registerMethod("ReadValue").onInterface(INTERFACE_NAME).withInputParamNames("options").withOutputParamNames("value").implementedAs([this](sdbus::Result<std::vector<uint8_t>>&& result, std::map<std::string, sdbus::Variant> options){ this->ReadValue(std::move(result), std::move(options)); });
|
||||
object_.registerMethod("WriteValue").onInterface(INTERFACE_NAME).withInputParamNames("value", "options").implementedAs([this](sdbus::Result<>&& result, std::vector<uint8_t> value, std::map<std::string, sdbus::Variant> options){ this->WriteValue(std::move(result), std::move(value), std::move(options)); });
|
||||
object_.registerMethod("StartNotify").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->StartNotify(); });
|
||||
object_.registerMethod("StopNotify").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->StopNotify(); });
|
||||
object_.registerMethod("Confirm").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Confirm(); });
|
||||
object_.registerProperty("UUID").onInterface(INTERFACE_NAME).withGetter([this](){ return this->UUID(); });
|
||||
object_.registerProperty("Service").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Service(); });
|
||||
object_.registerProperty("Value").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Value(); });
|
||||
object_.registerProperty("Notifying").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Notifying(); });
|
||||
object_.registerProperty("Flags").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Flags(); });
|
||||
}
|
||||
|
||||
~GattCharacteristic1_adaptor() = default;
|
||||
|
||||
private:
|
||||
virtual void ReadValue(sdbus::Result<std::vector<uint8_t>>&& result, std::map<std::string, sdbus::Variant> options) = 0;
|
||||
virtual void WriteValue(sdbus::Result<>&& result, std::vector<uint8_t> value, std::map<std::string, sdbus::Variant> options) = 0;
|
||||
virtual void StartNotify() = 0;
|
||||
virtual void StopNotify() = 0;
|
||||
virtual void Confirm() = 0;
|
||||
|
||||
private:
|
||||
virtual std::string UUID() = 0;
|
||||
virtual sdbus::ObjectPath Service() = 0;
|
||||
virtual std::vector<uint8_t> Value() = 0;
|
||||
virtual bool Notifying() = 0;
|
||||
virtual std::vector<std::string> Flags() = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& object_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__gatt_manager_client_h__proxy__H__
|
||||
#define __sdbuscpp__gatt_manager_client_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class GattManager1_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.GattManager1";
|
||||
|
||||
protected:
|
||||
GattManager1_proxy(sdbus::IProxy& proxy)
|
||||
: proxy_(proxy)
|
||||
{
|
||||
}
|
||||
|
||||
~GattManager1_proxy() = default;
|
||||
|
||||
public:
|
||||
void RegisterApplication(const sdbus::ObjectPath& application, const std::map<std::string, sdbus::Variant>& options)
|
||||
{
|
||||
proxy_.callMethod("RegisterApplication").onInterface(INTERFACE_NAME).withArguments(application, options);
|
||||
}
|
||||
|
||||
void UnregisterApplication(const sdbus::ObjectPath& application)
|
||||
{
|
||||
proxy_.callMethod("UnregisterApplication").onInterface(INTERFACE_NAME).withArguments(application);
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IProxy& proxy_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__generated_dbus_bluez_gatt_service_server_h__adaptor__H__
|
||||
#define __sdbuscpp__generated_dbus_bluez_gatt_service_server_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class GattService1_adaptor
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.GattService1";
|
||||
|
||||
protected:
|
||||
GattService1_adaptor(sdbus::IObject& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.registerProperty("UUID").onInterface(INTERFACE_NAME).withGetter([this](){ return this->UUID(); });
|
||||
object_.registerProperty("Primary").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Primary(); });
|
||||
object_.registerProperty("Device").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Device(); });
|
||||
object_.registerProperty("Includes").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Includes(); });
|
||||
}
|
||||
|
||||
~GattService1_adaptor() = default;
|
||||
|
||||
private:
|
||||
virtual std::string UUID() = 0;
|
||||
virtual bool Primary() = 0;
|
||||
virtual sdbus::ObjectPath Device() = 0;
|
||||
virtual std::vector<sdbus::ObjectPath> Includes() = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& object_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__generated_dbus_bluez_le_advertisement_manager_client_h__proxy__H__
|
||||
#define __sdbuscpp__generated_dbus_bluez_le_advertisement_manager_client_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class LEAdvertisingManager1_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.LEAdvertisingManager1";
|
||||
|
||||
protected:
|
||||
LEAdvertisingManager1_proxy(sdbus::IProxy& proxy)
|
||||
: proxy_(proxy)
|
||||
{
|
||||
}
|
||||
|
||||
~LEAdvertisingManager1_proxy() = default;
|
||||
|
||||
public:
|
||||
void RegisterAdvertisement(const sdbus::ObjectPath& advertisement, const std::map<std::string, sdbus::Variant>& options)
|
||||
{
|
||||
proxy_.callMethod("RegisterAdvertisement").onInterface(INTERFACE_NAME).withArguments(advertisement, options);
|
||||
}
|
||||
|
||||
void UnregisterAdvertisement(const sdbus::ObjectPath& service)
|
||||
{
|
||||
proxy_.callMethod("UnregisterAdvertisement").onInterface(INTERFACE_NAME).withArguments(service);
|
||||
}
|
||||
|
||||
public:
|
||||
uint8_t ActiveInstances()
|
||||
{
|
||||
return proxy_.getProperty("ActiveInstances").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
uint8_t SupportedInstances()
|
||||
{
|
||||
return proxy_.getProperty("SupportedInstances").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::vector<std::string> SupportedIncludes()
|
||||
{
|
||||
return proxy_.getProperty("SupportedIncludes").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::vector<std::string> SupportedSecondaryChannels()
|
||||
{
|
||||
return proxy_.getProperty("SupportedSecondaryChannels").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::vector<std::string> SupportedFeatures()
|
||||
{
|
||||
return proxy_.getProperty("SupportedFeatures").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::map<std::string, sdbus::Variant> SupportedCapabilities()
|
||||
{
|
||||
return proxy_.getProperty("SupportedCapabilities").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IProxy& proxy_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__generated_dbus_bluez_le_advertisement_server_h__adaptor__H__
|
||||
#define __sdbuscpp__generated_dbus_bluez_le_advertisement_server_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace bluez {
|
||||
|
||||
class LEAdvertisement1_adaptor
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.bluez.LEAdvertisement1";
|
||||
|
||||
protected:
|
||||
LEAdvertisement1_adaptor(sdbus::IObject& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.registerMethod("Release").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Release(); });
|
||||
object_.registerProperty("Type").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Type(); });
|
||||
object_.registerProperty("ServiceUUIDs").onInterface(INTERFACE_NAME).withGetter([this](){ return this->ServiceUUIDs(); });
|
||||
object_.registerProperty("ManufacturerData").onInterface(INTERFACE_NAME).withGetter([this](){ return this->ManufacturerData(); });
|
||||
object_.registerProperty("SolicitUUIDs").onInterface(INTERFACE_NAME).withGetter([this](){ return this->SolicitUUIDs(); });
|
||||
object_.registerProperty("ServiceData").onInterface(INTERFACE_NAME).withGetter([this](){ return this->ServiceData(); });
|
||||
object_.registerProperty("Includes").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Includes(); });
|
||||
object_.registerProperty("LocalName").onInterface(INTERFACE_NAME).withGetter([this](){ return this->LocalName(); });
|
||||
object_.registerProperty("Duration").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Duration(); });
|
||||
object_.registerProperty("Timeout").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Timeout(); });
|
||||
object_.registerProperty("MinInterval").onInterface(INTERFACE_NAME).withGetter([this](){ return this->MinInterval(); });
|
||||
object_.registerProperty("MaxInterval").onInterface(INTERFACE_NAME).withGetter([this](){ return this->MaxInterval(); });
|
||||
object_.registerProperty("TxPower").onInterface(INTERFACE_NAME).withGetter([this](){ return this->TxPower(); });
|
||||
}
|
||||
|
||||
~LEAdvertisement1_adaptor() = default;
|
||||
|
||||
private:
|
||||
virtual void Release() = 0;
|
||||
|
||||
private:
|
||||
virtual std::string Type() = 0;
|
||||
virtual std::vector<std::string> ServiceUUIDs() = 0;
|
||||
virtual std::map<std::string, sdbus::Variant> ManufacturerData() = 0;
|
||||
virtual std::vector<std::string> SolicitUUIDs() = 0;
|
||||
virtual std::map<std::string, sdbus::Variant> ServiceData() = 0;
|
||||
virtual std::vector<std::string> Includes() = 0;
|
||||
virtual std::string LocalName() = 0;
|
||||
virtual uint16_t Duration() = 0;
|
||||
virtual uint16_t Timeout() = 0;
|
||||
virtual uint32_t MinInterval() = 0;
|
||||
virtual uint32_t MaxInterval() = 0;
|
||||
virtual int16_t TxPower() = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& object_;
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.bluez.AdvertisementMonitor1">
|
||||
<method name="Release">
|
||||
</method>
|
||||
<method name="Activate">
|
||||
</method>
|
||||
<method name="DeviceFound">
|
||||
<arg type='o' name="device" direction="in"/>
|
||||
</method>
|
||||
<method name="DeviceLost">
|
||||
<arg type='o' name="device" direction="in"/>
|
||||
</method>
|
||||
|
||||
<property name="Type" type="s" access="read">
|
||||
</property>
|
||||
<property name="RSSILowThreshold" type="n" access="read">
|
||||
</property>
|
||||
<property name="RSSIHighThreshold" type="n" access="read">
|
||||
</property>
|
||||
<property name="RSSISamplingPeriod" type="q" access="read">
|
||||
</property>
|
||||
<property name="Patterns" type="a(yyay)" access="read">
|
||||
</property>
|
||||
</interface>
|
||||
</node>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.bluez.AdvertisementMonitorManager1">
|
||||
<method name="RegisterMonitor">
|
||||
<arg name="application" type="o" direction="in" />
|
||||
</method>
|
||||
<method name="UnregisterMonitor">
|
||||
<arg name="application" type="o" direction="in" />
|
||||
</method>
|
||||
<property name="SupportedMonitorTypes" type="as" access="read" />
|
||||
<property name="SupportedFeatures" type="as" access="read" />
|
||||
</interface>
|
||||
</node>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.bluez.GattCharacteristic1">
|
||||
<method name="ReadValue">
|
||||
<annotation name="org.freedesktop.DBus.Method.Async" value="server" />
|
||||
<arg name="options" type="a{sv}" direction="in"/>
|
||||
<arg name="value" type="ay" direction="out"/>
|
||||
</method>
|
||||
<method name="WriteValue">
|
||||
<annotation name="org.freedesktop.DBus.Method.Async" value="server" />
|
||||
<arg name="value" type="ay" direction="in"/>
|
||||
<arg name="options" type="a{sv}" direction="in"/>
|
||||
</method>
|
||||
<method name="StartNotify">
|
||||
</method>
|
||||
<method name="StopNotify">
|
||||
</method>
|
||||
<method name="Confirm">
|
||||
</method>
|
||||
|
||||
<property name="UUID" type="s" access="read"></property>
|
||||
<property name="Service" type="o" access="read"></property>
|
||||
<property name="Value" type="ay" access="read"></property>
|
||||
<property name="Notifying" type="b" access="read"></property>
|
||||
<property name="Flags" type="as" access="read"></property>
|
||||
</interface>
|
||||
</node>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.bluez.GattManager1">
|
||||
<method name="RegisterApplication">
|
||||
<arg name="application" type="o" direction="in" />
|
||||
<arg name="options" type="a{sv}" direction="in" />
|
||||
</method>
|
||||
<method name="UnregisterApplication">
|
||||
<arg name="application" type="o" direction="in" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.bluez.GattService1">
|
||||
<property name="UUID" type="s" access="read"></property>
|
||||
<property name="Primary" type="b" access="read"></property>
|
||||
<property name="Device" type="o" access="read"></property>
|
||||
<property name="Includes" type="ao" access="read"></property>
|
||||
</interface>
|
||||
</node>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE node PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.bluez.LEAdvertisement1">
|
||||
<method name="Release"/>
|
||||
<property name="Type" type="s" access="read"/>
|
||||
<property name="ServiceUUIDs" type="as" access="read"/>
|
||||
<property name="ManufacturerData" type="a{sv}" access="read"/>
|
||||
<property name="SolicitUUIDs" type="as" access="read"/>
|
||||
<property name="ServiceData" type="a{sv}" access="read"/>
|
||||
<property name="Includes" type="as" access="read"/>
|
||||
<property name="LocalName" type="s" access="read"/>
|
||||
<property name="Duration" type="q" access="read"/>
|
||||
<property name="Timeout" type="q" access="read"/>
|
||||
<property name="MinInterval" type="u" access="read"/>
|
||||
<property name="MaxInterval" type="u" access="read"/>
|
||||
<property name="TxPower" type="n" access="read"/>
|
||||
</interface>
|
||||
</node>
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.bluez.LEAdvertisingManager1">
|
||||
<method name="RegisterAdvertisement">
|
||||
<arg name="advertisement" type="o" direction="in" />
|
||||
<arg name="options" type="a{sv}" direction="in" />
|
||||
</method>
|
||||
<method name="UnregisterAdvertisement">
|
||||
<arg name="service" type="o" direction="in" />
|
||||
</method>
|
||||
<property name="ActiveInstances" type="y" access="read" />
|
||||
<property name="SupportedInstances" type="y" access="read" />
|
||||
<property name="SupportedIncludes" type="as" access="read" />
|
||||
<property name="SupportedSecondaryChannels" type="as" access="read" />
|
||||
<property name="SupportedFeatures" type="as" access="read" />
|
||||
<property name="SupportedCapabilities" type="a{sv}" access="read" />
|
||||
</interface>
|
||||
</node>
|
||||
@@ -196,13 +196,15 @@ ImplementationPlatform::CreateBluetoothClassicMedium(
|
||||
}
|
||||
|
||||
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
|
||||
BluetoothAdapter &) {
|
||||
return std::make_unique<linux::BleMedium>();
|
||||
BluetoothAdapter &adapter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleMedium>
|
||||
ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter &adapter) {
|
||||
return std::make_unique<linux::BleV2Medium>();
|
||||
return std::make_unique<linux::BleV2Medium>(
|
||||
linux::getSystemBusConnection(),
|
||||
dynamic_cast<linux::BluetoothAdapter &>(adapter));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Reference in New Issue
Block a user