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/fidl/cpp/binding.h"
20 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/server_base.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
22 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt.h"
23 
24 namespace bthost {
25 
26 class Gatt2RemoteServiceServer
27     : public GattServerBase<fuchsia::bluetooth::gatt2::RemoteService> {
28  public:
29   // The maximum number of pending notification values per
30   // CharacteristicNotifier (for flow control). If exceeded, the notifier
31   // protocol is closed.
32   static const size_t kMaxPendingNotifierValues = 20;
33 
34   Gatt2RemoteServiceServer(
35       bt::gatt::RemoteService::WeakPtr service,
36       bt::gatt::GATT::WeakPtr gatt,
37       bt::PeerId peer_id,
38       fidl::InterfaceRequest<fuchsia::bluetooth::gatt2::RemoteService> request);
39   ~Gatt2RemoteServiceServer() override;
40 
41   void Close(zx_status_t status);
42 
43  private:
44   using NotifierId = uint64_t;
45 
46   struct CharacteristicNotifier {
47     bt::gatt::IdType handler_id;
48     bt::gatt::CharacteristicHandle characteristic_handle;
49     fidl::InterfacePtr<fuchsia::bluetooth::gatt2::CharacteristicNotifier>
50         notifier;
51     // For flow control, values are only sent when the client responds to the
52     // previous value with an acknowledgement. This variable stores the queued
53     // values.
54     std::queue<fuchsia::bluetooth::gatt2::ReadValue> queued_values;
55     // `last_value_ack` defaults to true so that the first notification queued
56     // up is sent to the FIDL client immediately.
57     bool last_value_ack = true;
58   };
59 
60   // fuchsia::bluetooth::gatt2::RemoteService overrides:
61   void DiscoverCharacteristics(
62       DiscoverCharacteristicsCallback callback) override;
63 
64   void ReadByType(::fuchsia::bluetooth::Uuid uuid,
65                   ReadByTypeCallback callback) override;
66 
67   void ReadCharacteristic(::fuchsia::bluetooth::gatt2::Handle handle,
68                           ::fuchsia::bluetooth::gatt2::ReadOptions options,
69                           ReadCharacteristicCallback callback) override;
70 
71   void WriteCharacteristic(::fuchsia::bluetooth::gatt2::Handle handle,
72                            ::std::vector<uint8_t> value,
73                            ::fuchsia::bluetooth::gatt2::WriteOptions options,
74                            WriteCharacteristicCallback callback) override;
75 
76   void ReadDescriptor(::fuchsia::bluetooth::gatt2::Handle handle,
77                       ::fuchsia::bluetooth::gatt2::ReadOptions options,
78                       ReadDescriptorCallback callback) override;
79 
80   void WriteDescriptor(::fuchsia::bluetooth::gatt2::Handle handle,
81                        ::std::vector<uint8_t> value,
82                        ::fuchsia::bluetooth::gatt2::WriteOptions options,
83                        WriteDescriptorCallback callback) override;
84 
85   void RegisterCharacteristicNotifier(
86       ::fuchsia::bluetooth::gatt2::Handle handle,
87       ::fidl::InterfaceHandle<
88           ::fuchsia::bluetooth::gatt2::CharacteristicNotifier> notifier,
89       RegisterCharacteristicNotifierCallback callback) override;
90 
91   // Send the next notifier value in the queue if the client acknowledged the
92   // previous value.
93   void MaybeNotifyNextValue(NotifierId notifier_id);
94 
95   void OnCharacteristicNotifierError(NotifierId notifier_id,
96                                      bt::gatt::CharacteristicHandle char_handle,
97                                      bt::gatt::IdType handler_id);
98 
99   // The remote GATT service that backs this service.
100   bt::gatt::RemoteService::WeakPtr service_;
101 
102   NotifierId next_notifier_id_ = 0u;
103   std::unordered_map<NotifierId, CharacteristicNotifier>
104       characteristic_notifiers_;
105 
106   // The peer that is serving this service.
107   bt::PeerId peer_id_;
108 
109   WeakSelf<Gatt2RemoteServiceServer> weak_self_;
110 };
111 
112 }  // namespace bthost
113