1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #pragma once 16 17 #include <fuchsia/bluetooth/gatt2/cpp/fidl.h> 18 19 #include "lib/zx/eventpair.h" 20 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/gatt2_server_ids.h" 21 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/server_base.h" 22 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h" 23 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt.h" 24 25 namespace bthost { 26 27 // Implements the gatt2::Server FIDL interface. 28 // TODO(fxbug.dev/42054947): Support sending gatt2::LocalService::PeerUpdate. 29 // TODO(fxbug.dev/42147529): Support GATT service includes. 30 // TODO(fxbug.dev/42180948): Support OnSuppressDiscovery 31 class Gatt2ServerServer 32 : public GattServerBase<fuchsia::bluetooth::gatt2::Server> { 33 public: 34 // Arbitrary; we only refresh credits when the peer starts to get low. 35 // The current implementation does not support a value of 0. 36 static const uint8_t REFRESH_CREDITS_AT = 3; 37 38 // |gatt| - The GATT instance underlying this Server. 39 // |request| - The FIDL request. 40 Gatt2ServerServer( 41 bt::gatt::GATT::WeakPtr gatt, 42 fidl::InterfaceRequest<fuchsia::bluetooth::gatt2::Server> request); 43 44 ~Gatt2ServerServer() override; 45 46 private: 47 struct Service { 48 // The LocalService FIDL proxy 49 fidl::InterfacePtr<fuchsia::bluetooth::gatt2::LocalService> local_svc_ptr; 50 51 // The credits available for this LocalService 52 int16_t credits = fuchsia::bluetooth::gatt2::INITIAL_VALUE_CHANGED_CREDITS; 53 }; 54 55 // ::fuchsia::bluetooth::gatt2::Server overrides: 56 void PublishService( 57 fuchsia::bluetooth::gatt2::ServiceInfo info, 58 fidl::InterfaceHandle<fuchsia::bluetooth::gatt2::LocalService> service, 59 PublishServiceCallback callback) override; 60 61 // Removes the service with the given |id| if it is known, usually as a result 62 // of FIDL connection errors (such as handle closure). 63 void RemoveService(InternalServiceId id); 64 65 // Handles the ::fuchsia::bluetooth:gatt2::Server OnSuppressDiscovery event. 66 void OnSuppressDiscovery(InternalServiceId service_id); 67 68 // If the update has the required fields and there are credits available, 69 // subtracts a credit from the service and returns true. Otherwise, returns 70 // false. 71 bool ValidateValueChangedEvent( 72 InternalServiceId service_id, 73 const fuchsia::bluetooth::gatt2::ValueChangedParameters& update, 74 const char* update_type); 75 76 // Handles the ::fuchsia::bluetooth:gatt2::Server OnNotifyValue event. 77 void OnNotifyValue(InternalServiceId service_id, 78 fuchsia::bluetooth::gatt2::ValueChangedParameters update); 79 80 // Handles the ::fuchsia::bluetooth:gatt2::Server OnSuppressDiscovery event. 81 void OnIndicateValue(InternalServiceId service_id, 82 fuchsia::bluetooth::gatt2::ValueChangedParameters update, 83 zx::eventpair confirmation); 84 85 // Called when a remote device issues a read request to one of our services. 86 void OnReadRequest(bt::PeerId peer_id, 87 bt::gatt::IdType service_id, 88 bt::gatt::IdType id, 89 uint16_t offset, 90 bt::gatt::ReadResponder responder); 91 92 // Called when a remote device issues a write request to one of our services. 93 void OnWriteRequest(bt::PeerId peer_id, 94 bt::gatt::IdType service_id, 95 bt::gatt::IdType id, 96 uint16_t offset, 97 const bt::ByteBuffer& value, 98 bt::gatt::WriteResponder responder); 99 100 // Called when a remote device has configured notifications or indications on 101 // a local characteristic. 102 void OnClientCharacteristicConfiguration(bt::gatt::IdType service_id, 103 bt::gatt::IdType chrc_id, 104 bt::PeerId peer_id, 105 bool notify, 106 bool indicate); 107 108 // Subtract one credit from the client, potentially refreshing the credits to 109 // the client. 110 static void SubtractCredit(Service& svc); 111 112 // The mapping between internal service identifiers and FIDL Service 113 // implementations. 114 std::unordered_map<InternalServiceId, Service> services_; 115 116 // Mapping between client-provided Service IDs and internally-generated IDs. 117 // TODO(fxbug.dev/42147529): This will be necessary for supporting service 118 // includes. 119 std::unordered_map<ClientServiceId, InternalServiceId> service_id_mapping_; 120 121 // Keep this as the last member to make sure that all weak pointers are 122 // invalidated before other members get destroyed. 123 WeakSelf<Gatt2ServerServer> weak_self_; 124 125 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Gatt2ServerServer); 126 }; 127 128 } // namespace bthost 129