| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "device/bluetooth/floss/floss_gatt_manager_client.h" |
| |
| #include "base/logging.h" |
| #include "base/notreached.h" |
| |
| namespace floss { |
| namespace { |
| constexpr char kCharacteristics[] = "characteristics"; |
| constexpr char kDescriptors[] = "descriptors"; |
| constexpr char kIncludedServices[] = "included_services"; |
| constexpr char kInstanceId[] = "instance_id"; |
| constexpr char kKeySize[] = "key_size"; |
| constexpr char kPermissions[] = "permissions"; |
| constexpr char kProperties[] = "properties"; |
| constexpr char kServiceType[] = "service_type"; |
| constexpr char kUuid[] = "uuid"; |
| constexpr char kWriteType[] = "write_type"; |
| } // namespace |
| |
| namespace { |
| // Randomly generated UUID for use in this client. |
| constexpr char kDefaultGattManagerClientUuid[] = |
| "e060b902508c485f8b0e27639c7f2d41"; |
| |
| // Default to not requesting eatt support with gatt client. |
| constexpr bool kDefaultEattSupport = false; |
| |
| void HandleResponse(const char* method, DBusResult<Void> result) { |
| if (!result.has_value()) { |
| LOG(ERROR) << "Call failed: " << method << ": " << result.error(); |
| return; |
| } |
| |
| DVLOG(1) << method << " succeeded."; |
| } |
| } // namespace |
| |
| // Template specializations for dbus parsing |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, LePhy* phy) { |
| uint32_t value; |
| if (FlossDBusClient::ReadDBusParam(reader, &value)) { |
| *phy = static_cast<LePhy>(value); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const LePhy*) { |
| static DBusTypeInfo info{"u", "LePhy"}; |
| return info; |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const LePhy& phy) { |
| uint32_t value = static_cast<uint32_t>(phy); |
| WriteDBusParam(writer, value); |
| } |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| GattStatus* status) { |
| uint32_t value; |
| if (FlossDBusClient::ReadDBusParam(reader, &value)) { |
| *status = static_cast<GattStatus>(value); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const GattStatus& status) { |
| int32_t value = static_cast<int32_t>(status); |
| WriteDBusParam(writer, value); |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const GattStatus*) { |
| static DBusTypeInfo info{"u", "GattStatus"}; |
| return info; |
| } |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| GattWriteRequestStatus* status) { |
| uint32_t value; |
| if (FlossDBusClient::ReadDBusParam(reader, &value)) { |
| *status = static_cast<GattWriteRequestStatus>(value); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const GattWriteRequestStatus*) { |
| static DBusTypeInfo info{"u", "GattWriteRequestStatus"}; |
| return info; |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const AuthRequired& auth_req) { |
| int32_t value = static_cast<int32_t>(auth_req); |
| WriteDBusParam(writer, value); |
| } |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| WriteType* write_type) { |
| uint32_t value; |
| if (FlossDBusClient::ReadDBusParam(reader, &value)) { |
| *write_type = static_cast<WriteType>(value); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const WriteType*) { |
| static DBusTypeInfo info{"u", "WriteType"}; |
| return info; |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const WriteType& write_type) { |
| uint32_t value = static_cast<uint32_t>(write_type); |
| WriteDBusParam(writer, value); |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const GattService& service) { |
| dbus::MessageWriter array(nullptr); |
| |
| writer->OpenArray("{sv}", &array); |
| WriteDictEntry(&array, kUuid, service.uuid); |
| WriteDictEntry(&array, kInstanceId, service.instance_id); |
| WriteDictEntry(&array, kServiceType, service.service_type); |
| WriteDictEntry(&array, kCharacteristics, service.characteristics); |
| WriteDictEntry(&array, kIncludedServices, service.included_services); |
| writer->CloseContainer(&array); |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const GattCharacteristic& characteristic) { |
| dbus::MessageWriter array(nullptr); |
| |
| writer->OpenArray("{sv}", &array); |
| WriteDictEntry(&array, kInstanceId, characteristic.instance_id); |
| WriteDictEntry(&array, kProperties, characteristic.properties); |
| WriteDictEntry(&array, kPermissions, characteristic.permissions); |
| WriteDictEntry(&array, kKeySize, characteristic.key_size); |
| WriteDictEntry(&array, kWriteType, characteristic.write_type); |
| WriteDictEntry(&array, kDescriptors, characteristic.descriptors); |
| writer->CloseContainer(&array); |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const GattDescriptor& descriptor) { |
| dbus::MessageWriter array(nullptr); |
| |
| writer->OpenArray("{sv}", &array); |
| WriteDictEntry(&array, kUuid, descriptor.uuid); |
| WriteDictEntry(&array, kInstanceId, descriptor.instance_id); |
| WriteDictEntry(&array, kPermissions, descriptor.permissions); |
| writer->CloseContainer(&array); |
| } |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| GattDescriptor* descriptor) { |
| static FlossDBusClient::StructReader<GattDescriptor> struct_reader({ |
| {kUuid, CreateFieldReader(&GattDescriptor::uuid)}, |
| {kInstanceId, CreateFieldReader(&GattDescriptor::instance_id)}, |
| {kPermissions, CreateFieldReader(&GattDescriptor::permissions)}, |
| }); |
| |
| return struct_reader.ReadDBusParam(reader, descriptor); |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const GattDescriptor*) { |
| static DBusTypeInfo info{"a{sv}", "GattDescriptor"}; |
| return info; |
| } |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| GattCharacteristic* characteristic) { |
| static FlossDBusClient::StructReader<GattCharacteristic> struct_reader({ |
| {kUuid, CreateFieldReader(&GattCharacteristic::uuid)}, |
| {kInstanceId, CreateFieldReader(&GattCharacteristic::instance_id)}, |
| {kProperties, CreateFieldReader(&GattCharacteristic::properties)}, |
| {kKeySize, CreateFieldReader(&GattCharacteristic::key_size)}, |
| {kWriteType, CreateFieldReader(&GattCharacteristic::write_type)}, |
| {kDescriptors, CreateFieldReader(&GattCharacteristic::descriptors)}, |
| }); |
| |
| return struct_reader.ReadDBusParam(reader, characteristic); |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const GattCharacteristic*) { |
| static DBusTypeInfo info{"a{sv}", "GattCharacteristic"}; |
| return info; |
| } |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| GattService* service) { |
| static FlossDBusClient::StructReader<GattService> struct_reader({ |
| {kUuid, CreateFieldReader(&GattService::uuid)}, |
| {kInstanceId, CreateFieldReader(&GattService::instance_id)}, |
| {kServiceType, CreateFieldReader(&GattService::service_type)}, |
| {kCharacteristics, CreateFieldReader(&GattService::characteristics)}, |
| {kIncludedServices, CreateFieldReader(&GattService::included_services)}, |
| }); |
| |
| return struct_reader.ReadDBusParam(reader, service); |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const GattService*) { |
| static DBusTypeInfo info{"a{sv}", "GattService"}; |
| return info; |
| } |
| |
| GattDescriptor::GattDescriptor() = default; |
| GattDescriptor::~GattDescriptor() = default; |
| |
| GattCharacteristic::GattCharacteristic() = default; |
| GattCharacteristic::GattCharacteristic(const GattCharacteristic&) = default; |
| GattCharacteristic::~GattCharacteristic() = default; |
| |
| GattService::GattService() = default; |
| GattService::GattService(const GattService&) = default; |
| GattService::~GattService() = default; |
| |
| const char FlossGattManagerClient::kExportedCallbacksPath[] = |
| "/org/chromium/bluetooth/gattclient"; |
| |
| // static |
| std::unique_ptr<FlossGattManagerClient> FlossGattManagerClient::Create() { |
| return std::make_unique<FlossGattManagerClient>(); |
| } |
| |
| FlossGattManagerClient::FlossGattManagerClient() = default; |
| FlossGattManagerClient::~FlossGattManagerClient() { |
| if (bus_) { |
| gatt_client_exported_callback_manager_.UnexportCallback( |
| dbus::ObjectPath(kExportedCallbacksPath)); |
| gatt_server_exported_callback_manager_.UnexportCallback( |
| dbus::ObjectPath(kExportedCallbacksPath)); |
| } |
| } |
| |
| void FlossGattManagerClient::AddObserver(FlossGattClientObserver* observer) { |
| gatt_client_observers_.AddObserver(observer); |
| } |
| |
| void FlossGattManagerClient::AddServerObserver( |
| FlossGattServerObserver* observer) { |
| gatt_server_observers_.AddObserver(observer); |
| } |
| |
| void FlossGattManagerClient::RemoveObserver(FlossGattClientObserver* observer) { |
| gatt_client_observers_.RemoveObserver(observer); |
| } |
| |
| void FlossGattManagerClient::RemoveServerObserver( |
| FlossGattServerObserver* observer) { |
| gatt_server_observers_.RemoveObserver(observer); |
| } |
| |
| void FlossGattManagerClient::Connect(ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const BluetoothTransport& transport, |
| bool is_direct) { |
| // Opportunistic connections should be false because we want connections to |
| // immediately fail with timeout if it doesn't work out. |
| const bool opportunistic = false; |
| |
| // We want a phy to be chosen automatically. |
| const LePhy phy = LePhy::kInvalid; |
| |
| CallGattMethod<Void>(std::move(callback), gatt::kClientConnect, client_id_, |
| remote_device, is_direct, transport, opportunistic, phy); |
| } |
| |
| void FlossGattManagerClient::Disconnect(ResponseCallback<Void> callback, |
| const std::string& remote_device) { |
| CallGattMethod<Void>(std::move(callback), gatt::kClientDisconnect, client_id_, |
| remote_device); |
| } |
| |
| void FlossGattManagerClient::BeginReliableWrite( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device) { |
| CallGattMethod<Void>(std::move(callback), gatt::kBeginReliableWrite, |
| client_id_, remote_device); |
| } |
| |
| void FlossGattManagerClient::EndReliableWrite(ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| bool execute) { |
| CallGattMethod<Void>(std::move(callback), gatt::kEndReliableWrite, client_id_, |
| remote_device, execute); |
| } |
| |
| void FlossGattManagerClient::Refresh(ResponseCallback<Void> callback, |
| const std::string& remote_device) { |
| CallGattMethod<Void>(std::move(callback), gatt::kRefreshDevice, client_id_, |
| remote_device); |
| } |
| |
| void FlossGattManagerClient::DiscoverAllServices( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device) { |
| CallGattMethod<Void>(std::move(callback), gatt::kDiscoverServices, client_id_, |
| remote_device); |
| } |
| |
| void FlossGattManagerClient::DiscoverServiceByUuid( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const device::BluetoothUUID& uuid) { |
| CallGattMethod<Void>(std::move(callback), gatt::kDiscoverServiceByUuid, |
| client_id_, remote_device, uuid.canonical_value()); |
| } |
| |
| void FlossGattManagerClient::ReadCharacteristic( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const int32_t handle, |
| const AuthRequired auth_required) { |
| CallGattMethod<Void>(std::move(callback), gatt::kReadCharacteristic, |
| client_id_, remote_device, handle, auth_required); |
| } |
| |
| void FlossGattManagerClient::ReadUsingCharacteristicUuid( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const device::BluetoothUUID& uuid, |
| const int32_t start_handle, |
| const int32_t end_handle, |
| const AuthRequired auth_required) { |
| CallGattMethod<Void>(std::move(callback), gatt::kReadUsingCharacteristicUuid, |
| client_id_, remote_device, uuid.canonical_value(), |
| start_handle, end_handle, auth_required); |
| } |
| |
| void FlossGattManagerClient::WriteCharacteristic( |
| ResponseCallback<GattWriteRequestStatus> callback, |
| const std::string& remote_device, |
| const int32_t handle, |
| const WriteType write_type, |
| const AuthRequired auth_required, |
| const std::vector<uint8_t> data) { |
| CallGattMethod(std::move(callback), gatt::kWriteCharacteristic, client_id_, |
| remote_device, handle, write_type, auth_required, data); |
| } |
| |
| void FlossGattManagerClient::ReadDescriptor(ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const int32_t handle, |
| const AuthRequired auth_required) { |
| CallGattMethod<Void>(std::move(callback), gatt::kReadDescriptor, client_id_, |
| remote_device, handle, auth_required); |
| } |
| |
| void FlossGattManagerClient::WriteDescriptor(ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const int32_t handle, |
| const AuthRequired auth_required, |
| const std::vector<uint8_t> data) { |
| CallGattMethod<Void>(std::move(callback), gatt::kWriteDescriptor, client_id_, |
| remote_device, handle, auth_required, data); |
| } |
| |
| void FlossGattManagerClient::RegisterForNotification( |
| ResponseCallback<GattStatus> callback, |
| const std::string& remote_device, |
| const int32_t handle) { |
| const bool enable_notification = true; |
| CallGattMethod<Void>( |
| base::BindOnce(&FlossGattManagerClient::OnRegisterNotificationResponse, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback), |
| enable_notification), |
| gatt::kRegisterForNotification, client_id_, remote_device, handle, |
| enable_notification); |
| } |
| |
| void FlossGattManagerClient::UnregisterNotification( |
| ResponseCallback<GattStatus> callback, |
| const std::string& remote_device, |
| const int32_t handle) { |
| const bool enable_notification = false; |
| CallGattMethod<Void>( |
| base::BindOnce(&FlossGattManagerClient::OnRegisterNotificationResponse, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback), |
| enable_notification), |
| gatt::kRegisterForNotification, client_id_, remote_device, handle, |
| enable_notification); |
| } |
| |
| void FlossGattManagerClient::ReadRemoteRssi(ResponseCallback<Void> callback, |
| const std::string& remote_device) { |
| CallGattMethod<Void>(std::move(callback), gatt::kReadRemoteRssi, client_id_, |
| remote_device); |
| } |
| |
| void FlossGattManagerClient::ConfigureMTU(ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const int32_t mtu) { |
| CallGattMethod<Void>(std::move(callback), gatt::kConfigureMtu, client_id_, |
| remote_device, mtu); |
| } |
| |
| void FlossGattManagerClient::UpdateConnectionParameters( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const int32_t min_interval, |
| const int32_t max_interval, |
| const int32_t latency, |
| const int32_t timeout, |
| const uint16_t min_ce_len, |
| const uint16_t max_ce_len) { |
| CallGattMethod<Void>(std::move(callback), gatt::kConnectionParameterUpdate, |
| client_id_, remote_device, min_interval, max_interval, |
| latency, timeout, min_ce_len, max_ce_len); |
| } |
| |
| void FlossGattManagerClient::UnregisterServer(ResponseCallback<Void> callback) { |
| CallGattMethod<Void>(std::move(callback), gatt::kUnregisterServer, |
| server_id_); |
| } |
| |
| void FlossGattManagerClient::ServerConnect( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| const BluetoothTransport& transport) { |
| // Connect immediately, instead of when next seen. |
| constexpr bool is_direct = true; |
| |
| CallGattMethod<Void>(std::move(callback), gatt::kServerConnect, server_id_, |
| remote_device, is_direct, transport); |
| } |
| |
| void FlossGattManagerClient::ServerDisconnect( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device) { |
| CallGattMethod<Void>(std::move(callback), gatt::kServerDisconnect, server_id_, |
| remote_device); |
| } |
| |
| void FlossGattManagerClient::ServerSetPreferredPhy( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| LePhy tx_phy, |
| LePhy rx_phy, |
| int32_t phy_options) { |
| CallGattMethod<Void>(std::move(callback), gatt::kServerSetPreferredPhy, |
| server_id_, remote_device, tx_phy, rx_phy, phy_options); |
| } |
| |
| void FlossGattManagerClient::ServerReadPhy(ResponseCallback<Void> callback, |
| const std::string& remote_device) { |
| CallGattMethod<Void>(std::move(callback), gatt::kServerReadPhy, server_id_, |
| remote_device); |
| } |
| |
| void FlossGattManagerClient::AddService(ResponseCallback<Void> callback, |
| GattService service) { |
| CallGattMethod<Void>(std::move(callback), gatt::kAddService, server_id_, |
| service); |
| } |
| |
| void FlossGattManagerClient::RemoveService(ResponseCallback<Void> callback, |
| int32_t handle) { |
| CallGattMethod<Void>(std::move(callback), gatt::kRemoveService, server_id_, |
| handle); |
| } |
| |
| void FlossGattManagerClient::ClearServices(ResponseCallback<Void> callback) { |
| CallGattMethod<Void>(std::move(callback), gatt::kClearServices, server_id_); |
| } |
| |
| void FlossGattManagerClient::SendResponse(ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| int32_t request_id, |
| GattStatus status, |
| int32_t offset, |
| std::vector<uint8_t> value) { |
| CallGattMethod<Void>(std::move(callback), gatt::kSendResponse, server_id_, |
| remote_device, request_id, status, offset, value); |
| } |
| |
| void FlossGattManagerClient::ServerSendNotification( |
| ResponseCallback<Void> callback, |
| const std::string& remote_device, |
| int32_t handle, |
| bool confirm, |
| std::vector<uint8_t> value) { |
| CallGattMethod<Void>(std::move(callback), gatt::kServerSendNotification, |
| server_id_, remote_device, handle, confirm, value); |
| } |
| |
| void FlossGattManagerClient::Init(dbus::Bus* bus, |
| const std::string& service_name, |
| const int adapter_index, |
| base::OnceClosure on_ready) { |
| // Set field variables. |
| bus_ = bus; |
| service_name_ = service_name; |
| gatt_adapter_path_ = GenerateGattPath(adapter_index); |
| |
| // Initialize DBus object proxy. |
| dbus::ObjectProxy* object_proxy = |
| bus_->GetObjectProxy(service_name_, gatt_adapter_path_); |
| if (!object_proxy) { |
| LOG(ERROR) |
| << "FlossGattManagerClient couldn't init. Object proxy was null."; |
| return; |
| } |
| |
| // Register all callbacks. |
| gatt_client_exported_callback_manager_.Init(bus_.get()); |
| gatt_server_exported_callback_manager_.Init(bus_.get()); |
| |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnClientRegistered, |
| &FlossGattClientObserver::GattClientRegistered); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnClientConnectionState, |
| &FlossGattClientObserver::GattClientConnectionState); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnPhyUpdate, &FlossGattClientObserver::GattPhyUpdate); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnPhyRead, &FlossGattClientObserver::GattPhyRead); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnSearchComplete, &FlossGattClientObserver::GattSearchComplete); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnCharacteristicRead, |
| &FlossGattClientObserver::GattCharacteristicRead); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnCharacteristicWrite, |
| &FlossGattClientObserver::GattCharacteristicWrite); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnExecuteWrite, &FlossGattClientObserver::GattExecuteWrite); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnDescriptorRead, &FlossGattClientObserver::GattDescriptorRead); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnDescriptorWrite, &FlossGattClientObserver::GattDescriptorWrite); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnNotify, &FlossGattClientObserver::GattNotify); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnReadRemoteRssi, &FlossGattClientObserver::GattReadRemoteRssi); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnConfigureMtu, &FlossGattClientObserver::GattConfigureMtu); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnConnectionUpdated, |
| &FlossGattClientObserver::GattConnectionUpdated); |
| gatt_client_exported_callback_manager_.AddMethod( |
| gatt::kOnServiceChanged, &FlossGattClientObserver::GattServiceChanged); |
| |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerRegistered, |
| &FlossGattServerObserver::GattServerRegistered); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerConnectionState, |
| &FlossGattServerObserver::GattServerConnectionState); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerServiceAdded, |
| &FlossGattServerObserver::GattServerServiceAdded); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerServiceRemoved, |
| &FlossGattServerObserver::GattServerServiceRemoved); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerCharacteristicReadRequest, |
| &FlossGattServerObserver::GattServerCharacteristicReadRequest); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerDescriptorReadRequest, |
| &FlossGattServerObserver::GattServerDescriptorReadRequest); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerCharacteristicWriteRequest, |
| &FlossGattServerObserver::GattServerCharacteristicWriteRequest); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerDescriptorWriteRequest, |
| &FlossGattServerObserver::GattServerDescriptorWriteRequest); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnExecuteWrite, &FlossGattServerObserver::GattServerExecuteWrite); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerNotificationSent, |
| &FlossGattServerObserver::GattServerNotificationSent); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerMtuChanged, |
| &FlossGattServerObserver::GattServerMtuChanged); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnPhyUpdate, &FlossGattServerObserver::GattServerPhyUpdate); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnPhyRead, &FlossGattServerObserver::GattServerPhyRead); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnConnectionUpdated, |
| &FlossGattServerObserver::GattServerConnectionUpdate); |
| gatt_server_exported_callback_manager_.AddMethod( |
| gatt::kOnServerSubrateChange, |
| &FlossGattServerObserver::GattServerSubrateChange); |
| |
| // Export callbacks. |
| if (!gatt_client_exported_callback_manager_.ExportCallback( |
| dbus::ObjectPath(kExportedCallbacksPath), |
| weak_ptr_factory_.GetWeakPtr(), |
| base::BindOnce(&FlossGattManagerClient::RegisterClient, |
| weak_ptr_factory_.GetWeakPtr()))) { |
| LOG(ERROR) << "Unable to successfully export FlossGattClientObserver."; |
| return; |
| } |
| if (!gatt_server_exported_callback_manager_.ExportCallback( |
| dbus::ObjectPath(kExportedCallbacksPath), |
| weak_ptr_factory_.GetWeakPtr(), |
| base::BindOnce(&FlossGattManagerClient::RegisterServer, |
| weak_ptr_factory_.GetWeakPtr()))) { |
| LOG(ERROR) << "Unable to successfully export FlossGattServerObserver."; |
| return; |
| } |
| |
| property_msft_supported_.Init(this, bus_, service_name_, gatt_adapter_path_, |
| dbus::ObjectPath(kExportedCallbacksPath), |
| base::DoNothing()); |
| |
| // Everything is queued for registration so save |on_ready| for later. |
| on_ready_ = std::move(on_ready); |
| } |
| |
| void FlossGattManagerClient::RegisterClient() { |
| // Finish registering client. We will get gatt client id via |
| // |GattClientRegistered|. |
| CallGattMethod<Void>( |
| base::BindOnce(&HandleResponse, gatt::kRegisterClient), |
| gatt::kRegisterClient, std::string(kDefaultGattManagerClientUuid), |
| dbus::ObjectPath(kExportedCallbacksPath), kDefaultEattSupport); |
| } |
| |
| void FlossGattManagerClient::RegisterServer() { |
| // Finish registering server. We will get gatt server id via |
| // |GattClientRegistered|. |
| CallGattMethod<Void>( |
| base::BindOnce(&HandleResponse, gatt::kRegisterServer), |
| gatt::kRegisterServer, std::string(kDefaultGattManagerClientUuid), |
| dbus::ObjectPath(kExportedCallbacksPath), kDefaultEattSupport); |
| } |
| |
| void FlossGattManagerClient::CompleteInit() { |
| if (client_id_ && server_id_ && on_ready_) { |
| std::move(on_ready_).Run(); |
| } |
| } |
| |
| void FlossGattManagerClient::GattClientRegistered(GattStatus status, |
| int32_t client_id) { |
| if (client_id_ != 0) { |
| LOG(ERROR) << "Unexpected GattClientRegistered with id = " << client_id |
| << " when we already have id = " << client_id_; |
| return; |
| } |
| |
| if (status != GattStatus::kSuccess) { |
| LOG(ERROR) << "RegisterClient failed with status = " |
| << static_cast<uint32_t>(status); |
| return; |
| } |
| |
| client_id_ = client_id; |
| CompleteInit(); |
| } |
| |
| void FlossGattManagerClient::GattClientConnectionState(GattStatus status, |
| int32_t client_id, |
| bool connected, |
| std::string address) { |
| if (client_id != client_id_) { |
| return; |
| } |
| |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattClientConnectionState(status, client_id, connected, address); |
| } |
| } |
| |
| void FlossGattManagerClient::GattPhyUpdate(std::string address, |
| LePhy tx, |
| LePhy rx, |
| GattStatus status) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattPhyUpdate(address, tx, rx, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattPhyRead(std::string address, |
| LePhy tx, |
| LePhy rx, |
| GattStatus status) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattPhyRead(address, tx, rx, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattSearchComplete( |
| std::string address, |
| const std::vector<GattService>& services, |
| GattStatus status) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattSearchComplete(address, services, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattCharacteristicRead( |
| std::string address, |
| GattStatus status, |
| int32_t handle, |
| const std::vector<uint8_t>& data) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattCharacteristicRead(address, status, handle, data); |
| } |
| } |
| |
| void FlossGattManagerClient::GattCharacteristicWrite(std::string address, |
| GattStatus status, |
| int32_t handle) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattCharacteristicWrite(address, status, handle); |
| } |
| } |
| |
| void FlossGattManagerClient::GattExecuteWrite(std::string address, |
| GattStatus status) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattExecuteWrite(address, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattDescriptorRead( |
| std::string address, |
| GattStatus status, |
| int32_t handle, |
| const std::vector<uint8_t>& data) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattDescriptorRead(address, status, handle, data); |
| } |
| } |
| |
| void FlossGattManagerClient::GattDescriptorWrite(std::string address, |
| GattStatus status, |
| int32_t handle) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattDescriptorWrite(address, status, handle); |
| } |
| } |
| |
| void FlossGattManagerClient::GattNotify(std::string address, |
| int32_t handle, |
| const std::vector<uint8_t>& data) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattNotify(address, handle, data); |
| } |
| } |
| |
| void FlossGattManagerClient::GattReadRemoteRssi(std::string address, |
| int32_t rssi, |
| GattStatus status) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattReadRemoteRssi(address, rssi, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattConfigureMtu(std::string address, |
| int32_t mtu, |
| GattStatus status) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattConfigureMtu(address, mtu, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattConnectionUpdated(std::string address, |
| int32_t interval, |
| int32_t latency, |
| int32_t timeout, |
| GattStatus status) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattConnectionUpdated(address, interval, latency, timeout, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServiceChanged(std::string address) { |
| for (auto& observer : gatt_client_observers_) { |
| observer.GattServiceChanged(address); |
| } |
| } |
| |
| // TODO(b/193685841) - Floss currently doesn't emit a callback when |
| // a notification registers. Once a callback is available, we should report that |
| // via the callback here instead. |
| void FlossGattManagerClient::OnRegisterNotificationResponse( |
| ResponseCallback<GattStatus> callback, |
| bool is_registering, |
| DBusResult<Void> result) { |
| if (!result.has_value()) { |
| std::move(callback).Run(GattStatus::kError); |
| return; |
| } |
| |
| std::move(callback).Run(GattStatus::kSuccess); |
| } |
| |
| void FlossGattManagerClient::GattServerRegistered(GattStatus status, |
| int32_t server_id) { |
| if (server_id_ != 0) { |
| LOG(ERROR) << "Unexpected GattServerRegistered with id = " << server_id |
| << " when we already have id = " << server_id_; |
| return; |
| } |
| |
| if (status != GattStatus::kSuccess) { |
| LOG(ERROR) << "RegisterServer failed with status = " |
| << static_cast<uint32_t>(status); |
| return; |
| } |
| |
| server_id_ = server_id; |
| CompleteInit(); |
| } |
| |
| void FlossGattManagerClient::GattServerConnectionState(GattStatus status, |
| int32_t server_id, |
| bool connected, |
| std::string address) { |
| if (server_id != server_id_) { |
| return; |
| } |
| |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerConnectionState(status, server_id, connected, address); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerServiceAdded(GattStatus status, |
| GattService service) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerServiceAdded(status, service); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerServiceRemoved(GattStatus status, |
| int32_t handle) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerServiceRemoved(status, handle); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerCharacteristicReadRequest( |
| std::string address, |
| int32_t request_id, |
| int32_t offset, |
| bool is_long, |
| int32_t handle) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerCharacteristicReadRequest(address, request_id, offset, |
| is_long, handle); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerDescriptorReadRequest( |
| std::string address, |
| int32_t request_id, |
| int32_t offset, |
| bool is_long, |
| int32_t handle) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerDescriptorReadRequest(address, request_id, offset, |
| is_long, handle); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerCharacteristicWriteRequest( |
| std::string address, |
| int32_t request_id, |
| int32_t offset, |
| int32_t length, |
| bool is_prepared_write, |
| bool needs_response, |
| int32_t handle, |
| std::vector<uint8_t> value) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerCharacteristicWriteRequest( |
| address, request_id, offset, length, is_prepared_write, needs_response, |
| handle, value); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerDescriptorWriteRequest( |
| std::string address, |
| int32_t request_id, |
| int32_t offset, |
| int32_t length, |
| bool is_prepared_write, |
| bool needs_response, |
| int32_t handle, |
| std::vector<uint8_t> value) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerDescriptorWriteRequest(address, request_id, offset, |
| length, is_prepared_write, |
| needs_response, handle, value); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerExecuteWrite(std::string address, |
| int32_t request_id, |
| bool execute_write) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerExecuteWrite(address, request_id, execute_write); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerNotificationSent(std::string address, |
| GattStatus status) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerNotificationSent(address, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerMtuChanged(std::string address, |
| int32_t mtu) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerMtuChanged(address, mtu); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerPhyUpdate(std::string address, |
| LePhy tx_phy, |
| LePhy rx_phy, |
| GattStatus status) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerPhyUpdate(address, tx_phy, rx_phy, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerPhyRead(std::string address, |
| LePhy tx_phy, |
| LePhy rx_phy, |
| GattStatus status) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerPhyRead(address, tx_phy, rx_phy, status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerConnectionUpdate(std::string address, |
| int32_t interval, |
| int32_t latency, |
| int32_t timeout, |
| GattStatus status) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerConnectionUpdate(address, interval, latency, timeout, |
| status); |
| } |
| } |
| |
| void FlossGattManagerClient::GattServerSubrateChange(std::string address, |
| int32_t subrate_factor, |
| int32_t latency, |
| int32_t continuation_num, |
| int32_t timeout, |
| GattStatus status) { |
| for (auto& observer : gatt_server_observers_) { |
| observer.GattServerSubrateChange(address, subrate_factor, latency, |
| continuation_num, timeout, status); |
| } |
| } |
| |
| } // namespace floss |