diff --git a/internal/platform/implementation/linux/BUILD b/internal/platform/implementation/linux/BUILD index ad0cdfdf..a427f35a 100644 --- a/internal/platform/implementation/linux/BUILD +++ b/internal/platform/implementation/linux/BUILD @@ -76,6 +76,7 @@ cc_library( # "bluez_gatt_characteristic_client.h", "bluez_gatt_characteristic_server.h", "bluez_gatt_manager.h", + "bluez_gatt_profile.h", # "bluez_gatt_service_client.h", "bluez_gatt_service_server.h", "bluez_le_advertisement.h", diff --git a/internal/platform/implementation/linux/ble_gatt_server.cc b/internal/platform/implementation/linux/ble_gatt_server.cc index 927c6d62..0c2089ea 100644 --- a/internal/platform/implementation/linux/ble_gatt_server.cc +++ b/internal/platform/implementation/linux/ble_gatt_server.cc @@ -54,18 +54,24 @@ GattServer::CreateCharacteristic( << "' and message '" << e.getMessage() << "'"; return std::nullopt; } + auto profile = std::make_unique (system_bus_, bluez::gatt_profile_object_path( + std::string(service_uuid)), std::string(service_uuid)); + profile -> emitInterfacesAddedSignal(); if (service->AddCharacteristic(service_uuid, characteristic_uuid, permission, property)) { - bluez::GattManager manager(system_bus_, adapter_.GetObjectPath()); - try { - LOG(INFO) << __func__ << ": registering service " - << service->getObjectPath(); - manager.RegisterApplication("/", {}); - } catch (const sdbus::Error& e) { - DBUS_LOG_METHOD_CALL_ERROR(&manager, "RegisterApplication", e); - return std::nullopt; - } + try { + LOG(INFO)<< __func__ << ": Registering service on gattmanager"; + gatt_manager_ -> RegisterApplication(gatt_service_root_object_manager -> getObjectPath(), {}); + } catch (const sdbus::Error& e) { + LOG(ERROR) + << __func__ + << ": error calling RegisterAplication for GattManager with object path " + << gatt_manager_->getObjectPath() << " with name '" << e.getName() + << "' and message '" << e.getMessage() << "'"; + return std::nullopt; + } + services_.insert({service_uuid, std::move(service)}); diff --git a/internal/platform/implementation/linux/ble_gatt_server.h b/internal/platform/implementation/linux/ble_gatt_server.h index 2f3b75b5..65a64390 100644 --- a/internal/platform/implementation/linux/ble_gatt_server.h +++ b/internal/platform/implementation/linux/ble_gatt_server.h @@ -20,6 +20,8 @@ #include +#include "bluez_gatt_manager.h" +#include "bluez_gatt_profile.h" #include "absl/container/flat_hash_map.h" #include "absl/synchronization/mutex.h" #include "absl/types/optional.h" @@ -63,6 +65,8 @@ class GattServer : public api::ble_v2::GattServer { devices_(std::move(devices)), adapter_(adapter), local_peripheral_(adapter_), + gatt_service_root_object_manager(std::make_unique(system_bus_, "/com/google/nearby/medium/ble/gatt")), + gatt_manager_(std::make_unique(system_bus_, adapter_.GetObjectPath())), server_cb_(std::make_shared( std::move(server_cb))) {} ~GattServer() override = default; @@ -85,6 +89,11 @@ class GattServer : public api::ble_v2::GattServer { BluetoothAdapter adapter_; LocalBlePeripheral local_peripheral_; + std::unique_ptr gatt_service_root_object_manager; + absl::Mutex profiles_mutex_; + absl::flat_hash_map> gatt_profiles_; + ABSL_GUARDED_BY(profiles_mutex_) + std::unique_ptr gatt_manager_; std::shared_ptr server_cb_; absl::Mutex services_mutex_; absl::flat_hash_map> services_ diff --git a/internal/platform/implementation/linux/ble_medium.cc b/internal/platform/implementation/linux/ble_medium.cc new file mode 100644 index 00000000..2f4a3604 --- /dev/null +++ b/internal/platform/implementation/linux/ble_medium.cc @@ -0,0 +1,33 @@ +// 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_medium.h" + +#include +#include + +#include "absl/synchronization/mutex.h" +#include "internal/platform/implementation/ble.h" +#include "internal/platform/implementation/ble_v2.h" +#include "internal/platform/implementation/linux/ble_v2_medium.h" +#include "internal/platform/implementation/linux/bluetooth_adapter.h" +#include "internal/platform/logging.h" +#include "internal/platform/uuid.h" + +namespace nearby { +namespace linux { + + +} // namespace linux +} // namespace nearby \ No newline at end of file diff --git a/internal/platform/implementation/linux/ble_v2_medium.cc b/internal/platform/implementation/linux/ble_v2_medium.cc index bf1b082f..2cf555e1 100644 --- a/internal/platform/implementation/linux/ble_v2_medium.cc +++ b/internal/platform/implementation/linux/ble_v2_medium.cc @@ -43,7 +43,7 @@ BleV2Medium::BleV2Medium(BluetoothAdapter &adapter) devices_(std::make_unique( system_bus_, adapter_.GetObjectPath(), observers_)), // gatt_discovery_(std::make_shared(system_bus_)), - root_object_manager_(std::make_unique(*system_bus_)), + root_object_manager_(std::make_unique(*system_bus_, "/com/google/nearby/medium/ble/advertisement/monitor")), adv_monitor_manager_( bluez::AdvertisementMonitorManager:: DiscoverAdvertisementMonitorManager(*system_bus_, adapter_)), @@ -56,7 +56,7 @@ BleV2Medium::BleV2Medium(BluetoothAdapter &adapter) << ": Registering path /com/google/nearby/medium/ble/advertisement/monitor with AdvertisementMonitorManager at " << adv_monitor_manager_->getObjectPath(); try { - adv_monitor_manager_->RegisterMonitor("/com/google/nearby/medium/ble/advertisement/monitor"); + adv_monitor_manager_->RegisterMonitor(root_object_manager_->getObjectPath()); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(adv_monitor_manager_, "RegisterMonitor", e); } @@ -73,6 +73,11 @@ BleV2Medium::BleV2Medium(BluetoothAdapter &adapter) bool BleV2Medium::StartAdvertising( const api::ble_v2::BleAdvertisementData &advertising_data, api::ble_v2::AdvertiseParameters advertise_set_parameters) { + if (!advertising_data.is_extended_advertisement) + { + // can't send two LE advertisements at the same + return true; + } if (!adapter_.IsEnabled()) { LOG(WARNING) << "BLE cannot start advertising because the " "bluetooth adapter is not enabled."; diff --git a/internal/platform/implementation/linux/ble_v2_medium.h b/internal/platform/implementation/linux/ble_v2_medium.h index dea7cb22..a1187a3f 100644 --- a/internal/platform/implementation/linux/ble_v2_medium.h +++ b/internal/platform/implementation/linux/ble_v2_medium.h @@ -26,6 +26,7 @@ #include "absl/synchronization/mutex.h" #include "internal/platform/implementation/ble_v2.h" // #include "internal/platform/implementation/linux/ble_gatt_client.h" +#include "bluez_gatt_manager.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" @@ -142,7 +143,7 @@ class BleV2Medium final : public api::ble_v2::BleMedium { std::shared_ptr devices_; // std::shared_ptr gatt_discovery_; - std::unique_ptr root_object_manager_; + std::unique_ptr root_object_manager_; std::unique_ptr adv_monitor_manager_; absl::Mutex active_adv_monitors_mutex_; absl::flat_hash_map< diff --git a/internal/platform/implementation/linux/bluetooth_classic_device.cc b/internal/platform/implementation/linux/bluetooth_classic_device.cc index 544a1746..108a71bb 100644 --- a/internal/platform/implementation/linux/bluetooth_classic_device.cc +++ b/internal/platform/implementation/linux/bluetooth_classic_device.cc @@ -116,7 +116,8 @@ void MonitoredBluetoothDevice::onPropertiesChanged( } for (auto it = changedProperties.begin(); it != changedProperties.end(); - it++) { + it++) + { if (it->first == bluez::DEVICE_PROP_ADDRESS) { LOG(INFO) << __func__ << ": " << getObjectPath() << ": Notifying observers about address change"; @@ -124,6 +125,7 @@ void MonitoredBluetoothDevice::onPropertiesChanged( for (const auto &observer : observers_.GetObservers()) { observer->DeviceAddressChanged(*this, address); } + } else if (it->first == bluez::DEVICE_PROP_PAIRED) { LOG(INFO) << __func__ << ": " << getObjectPath() << "Notifying observers about paired status change."; @@ -137,7 +139,9 @@ void MonitoredBluetoothDevice::onPropertiesChanged( for (const auto &observer : observers_.GetObservers()) { observer->DeviceConnectedStateChanged(*this, it->second); } - } else if (it->first == bluez::DEVICE_NAME) { + } else if ( it -> first == "ServicesResolved"){ + LOG(INFO) << ": ServicesResolved"; + }else if (it->first == bluez::DEVICE_NAME) { auto callback = GetDiscoveryCallback(); if (callback != nullptr && callback->device_name_changed_cb != nullptr) callback->device_name_changed_cb(*this); diff --git a/internal/platform/implementation/linux/bluez.cc b/internal/platform/implementation/linux/bluez.cc index ba20e853..48c3532d 100644 --- a/internal/platform/implementation/linux/bluez.cc +++ b/internal/platform/implementation/linux/bluez.cc @@ -35,7 +35,13 @@ sdbus::ObjectPath profile_object_path(absl::string_view service_uuid) { absl::StrReplaceAll(service_uuid, {{"-", "_"}})); } -sdbus::ObjectPath adapter_object_path(absl::string_view name) { + sdbus::ObjectPath gatt_profile_object_path(absl::string_view service_uuid) { + return absl::Substitute( + "$0/profile_$1", + NEARBY_BLE_GATT_PROFILE_PATH_ROOT, + absl::StrReplaceAll(service_uuid, {{"-", "_"}})); +} + sdbus::ObjectPath adapter_object_path(absl::string_view name) { return absl::Substitute("/org/bluez/$0", name); } diff --git a/internal/platform/implementation/linux/bluez.h b/internal/platform/implementation/linux/bluez.h index 29ce772c..cd037f7b 100644 --- a/internal/platform/implementation/linux/bluez.h +++ b/internal/platform/implementation/linux/bluez.h @@ -49,10 +49,13 @@ static constexpr const char *DEVICE_NAME = "Name"; static constexpr const char *NEARBY_BLE_GATT_PATH_ROOT = "/com/google/nearby/medium/ble/gatt"; -std::string device_object_path(const sdbus::ObjectPath &adapter_object_path, + static constexpr const char *NEARBY_BLE_GATT_PROFILE_PATH_ROOT = + "/com/google/nearby/medium/ble/gatt/profile"; + std::string device_object_path(const sdbus::ObjectPath &adapter_object_path, absl::string_view mac_address); sdbus::ObjectPath profile_object_path(absl::string_view service_uuid); sdbus::ObjectPath adapter_object_path(absl::string_view name); +sdbus::ObjectPath gatt_profile_object_path(absl::string_view service_uuid); sdbus::ObjectPath gatt_service_path(size_t num); sdbus::ObjectPath gatt_characteristic_path( const sdbus::ObjectPath &service_path, size_t num); diff --git a/internal/platform/implementation/linux/bluez_advertisement_monitor.cc b/internal/platform/implementation/linux/bluez_advertisement_monitor.cc index 9418d110..2bc71f36 100644 --- a/internal/platform/implementation/linux/bluez_advertisement_monitor.cc +++ b/internal/platform/implementation/linux/bluez_advertisement_monitor.cc @@ -1,4 +1,7 @@ #include "internal/platform/implementation/linux/bluez_advertisement_monitor.h" + +#include + #include "internal/platform/byte_array.h" #include "internal/platform/implementation/ble_v2.h" #include "internal/platform/implementation/linux/dbus.h" @@ -57,7 +60,9 @@ void AdvertisementMonitor::DeviceFound(const sdbus::ObjectPath &device) { adv_data.service_data.emplace(*uuid, std::string(bytes.begin(), bytes.end())); } - // scan_callback_.advertisement_found_cb(*peripheral, adv_data); + auto id = std::stoull(std::regex_replace(peripheral->GetMacAddress(), + std::regex("[:\\-]"), ""), nullptr, 16); + scan_callback_.advertisement_found_cb(id, adv_data); } void AdvertisementMonitor::DeviceLost(const sdbus::ObjectPath &device) { diff --git a/internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h b/internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h index 8a05e976..196b5e96 100644 --- a/internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h +++ b/internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h @@ -31,10 +31,11 @@ class AdvertisementMonitorManager final org::bluez::AdvertisementMonitorManager1_proxy> { private: friend std::unique_ptr - std::make_unique(sdbus::IConnection &, - const BluetoothAdapter &); - AdvertisementMonitorManager(sdbus::IConnection &system_bus, - const BluetoothAdapter &adapter) + std::make_unique( + sdbus::IConnection &, const ::nearby::linux::BluetoothAdapter &); + AdvertisementMonitorManager( + sdbus::IConnection &system_bus, + const ::nearby::linux::BluetoothAdapter &adapter) : ProxyInterfaces(system_bus, "org.bluez", adapter.GetObjectPath()) { registerProxy(); } @@ -49,8 +50,9 @@ class AdvertisementMonitorManager final ~AdvertisementMonitorManager() { unregisterProxy(); } static std::unique_ptr - DiscoverAdvertisementMonitorManager(sdbus::IConnection &system_bus, - const BluetoothAdapter &adapter) { + DiscoverAdvertisementMonitorManager( + sdbus::IConnection &system_bus, + const ::nearby::linux::BluetoothAdapter &adapter) { bluez::BluezObjectManager manager(system_bus); std::map>> diff --git a/internal/platform/implementation/linux/bluez_gatt_profile.h b/internal/platform/implementation/linux/bluez_gatt_profile.h new file mode 100644 index 00000000..0c34063f --- /dev/null +++ b/internal/platform/implementation/linux/bluez_gatt_profile.h @@ -0,0 +1,63 @@ +// +// Created by root on 1/11/26. +// + +#ifndef WORKSPACE_BLUEZ_GATT_PROFILE_H +#define WORKSPACE_BLUEZ_GATT_PROFILE_H + +#include +#include +#include + +#include "generated/dbus/bluez/gatt_profile_server.h" +#include "internal/platform/logging.h" + +#include +#include +#include + +namespace nearby { + namespace linux { + namespace bluez { + class GattProfile + : public sdbus::AdaptorInterfaces { + public: + GattProfile(const GattProfile &) = delete; + GattProfile(GattProfile &&) = delete; + GattProfile &operator=(const GattProfile &) = delete; + GattProfile &operator=(GattProfile &&) = delete; + + GattProfile(sdbus::IConnection &system_bus, + sdbus::ObjectPath profile_path, std::string service_uuid) + : AdaptorInterfaces(system_bus, profile_path), + uuids_({service_uuid}) + + { + registerAdaptor(); + } + ~GattProfile() { unregisterAdaptor(); } + + void Release() override + { + LOG(INFO) << __func__ << ": Gatt profile released"; + }; + private: + std::string ToLowerAscii(std::string s) { + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return static_cast(std::tolower(c)); }); + return s; + } + std::vector UUIDs() override + { + LOG(INFO)<< __func__ << ": UUIDs called, returned: " << ToLowerAscii(uuids_[0]); + return uuids_; + }; + + std::vector uuids_; + + }; + } // namespace bluez + } // namespace linux +} // namespace nearby + +#endif //WORKSPACE_BLUEZ_GATT_PROFILE_H \ No newline at end of file diff --git a/internal/platform/implementation/linux/dbus.h b/internal/platform/implementation/linux/dbus.h index 18e7ca4f..ac48f5dd 100644 --- a/internal/platform/implementation/linux/dbus.h +++ b/internal/platform/implementation/linux/dbus.h @@ -51,10 +51,8 @@ class RootObjectManager final : public sdbus::AdaptorInterfaces { public: - // only used in ble advertisement monitoring for now. - // TODO: Remove hardcodinged va - explicit RootObjectManager(sdbus::IConnection &system_bus) - : AdaptorInterfaces(system_bus, "/com/google/nearby/medium/ble/advertisement/monitor") { + explicit RootObjectManager(sdbus::IConnection &system_bus, sdbus::ObjectPath path) + : AdaptorInterfaces(system_bus, path) { registerAdaptor(); } ~RootObjectManager() { unregisterAdaptor(); } diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/gatt_profile_server.h b/internal/platform/implementation/linux/generated/dbus/bluez/gatt_profile_server.h new file mode 100644 index 00000000..865e76bd --- /dev/null +++ b/internal/platform/implementation/linux/generated/dbus/bluez/gatt_profile_server.h @@ -0,0 +1,48 @@ + +/* + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! + */ + +#ifndef __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_gatt_profile_server_h__adaptor__H__ +#define __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_gatt_profile_server_h__adaptor__H__ + +#include +#include +#include + +namespace org { +namespace bluez { + +class GattProfile1_adaptor +{ +public: + static constexpr const char* INTERFACE_NAME = "org.bluez.GattProfile1"; + +protected: + GattProfile1_adaptor(sdbus::IObject& object) + : object_(&object) + { + object_->registerMethod("Release").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Release(); }); + object_->registerProperty("UUIDs").onInterface(INTERFACE_NAME).withGetter([this](){ return this->UUIDs(); }); + } + + GattProfile1_adaptor(const GattProfile1_adaptor&) = delete; + GattProfile1_adaptor& operator=(const GattProfile1_adaptor&) = delete; + GattProfile1_adaptor(GattProfile1_adaptor&&) = default; + GattProfile1_adaptor& operator=(GattProfile1_adaptor&&) = default; + + ~GattProfile1_adaptor() = default; + +private: + virtual void Release() = 0; + +private: + virtual std::vector UUIDs() = 0; + +private: + sdbus::IObject* object_; +}; + +}} // namespaces + +#endif diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.GattProfile1.xml b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.GattProfile1.xml new file mode 100644 index 00000000..83c46531 --- /dev/null +++ b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.GattProfile1.xml @@ -0,0 +1,8 @@ + + + + + + +