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 <lib/fit/function.h>
18 
19 #include <utility>
20 
21 #include "lib/fidl/cpp/binding.h"
22 #include "lib/fidl/cpp/interface_request.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
24 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
25 #include "pw_bluetooth_sapphire/internal/host/gap/adapter.h"
26 
27 namespace bt {
28 
29 namespace gap {
30 class Adapter;
31 }  // namespace gap
32 
33 namespace gatt {
34 class GATT;
35 }  // namespace gatt
36 
37 }  // namespace bt
38 
39 namespace bthost {
40 
41 // This class acts as a common base type for all FIDL interface servers. Its
42 // main purpose is to provide type erasure for the ServerBase template below.
43 class Server {
44  public:
45   virtual ~Server() = default;
46 
47   virtual void set_error_handler(fit::function<void(zx_status_t)> handler) = 0;
48 };
49 
50 // ServerBase is a common base implementation for FIDL interface servers.
51 template <typename Interface>
52 class ServerBase : public Server, public Interface {
53  public:
54   // Constructs a FIDL server by binding a fidl::InterfaceRequest.
ServerBase(Interface * impl,fidl::InterfaceRequest<Interface> request)55   ServerBase(Interface* impl, fidl::InterfaceRequest<Interface> request)
56       : ServerBase(impl, request.TakeChannel()) {}
57 
58   // Constructs a FIDL server by binding a zx::channel.
ServerBase(Interface * impl,zx::channel channel)59   ServerBase(Interface* impl, zx::channel channel)
60       : binding_(impl, std::move(channel)) {
61     PW_DCHECK(binding_.is_bound());
62   }
63 
64   ~ServerBase() override = default;
65 
set_error_handler(fit::function<void (zx_status_t)> handler)66   void set_error_handler(fit::function<void(zx_status_t)> handler) override {
67     binding_.set_error_handler(std::move(handler));
68   }
69 
70  protected:
binding()71   ::fidl::Binding<Interface>* binding() { return &binding_; }
72 
73  private:
74   // Holds the channel from the FIDL client.
75   ::fidl::Binding<Interface> binding_;
76 
77   // Binding cannot be copied or moved.
78   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(ServerBase);
79 };
80 
81 // Base template for GAP FIDL interface servers. The GAP profile is accessible
82 // through an Adapter object.
83 template <typename Interface>
84 class AdapterServerBase : public ServerBase<Interface> {
85  public:
AdapterServerBase(bt::gap::Adapter::WeakPtr adapter,Interface * impl,fidl::InterfaceRequest<Interface> request)86   AdapterServerBase(bt::gap::Adapter::WeakPtr adapter,
87                     Interface* impl,
88                     fidl::InterfaceRequest<Interface> request)
89       : AdapterServerBase(adapter, impl, request.TakeChannel()) {}
90 
AdapterServerBase(bt::gap::Adapter::WeakPtr adapter,Interface * impl,zx::channel channel)91   AdapterServerBase(bt::gap::Adapter::WeakPtr adapter,
92                     Interface* impl,
93                     zx::channel channel)
94       : ServerBase<Interface>(impl, std::move(channel)),
95         adapter_(std::move(adapter)) {
96     PW_DCHECK(adapter_.is_alive());
97   }
98 
99   ~AdapterServerBase() override = default;
100 
101  protected:
adapter()102   const bt::gap::Adapter::WeakPtr& adapter() const { return adapter_; }
103 
104  private:
105   bt::gap::Adapter::WeakPtr adapter_;
106 
107   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AdapterServerBase);
108 };
109 
110 // Base template for GATT FIDL interface servers. The GATT profile is accessible
111 // through an Adapter object.
112 template <typename Interface>
113 class GattServerBase : public ServerBase<Interface> {
114  public:
GattServerBase(bt::gatt::GATT::WeakPtr gatt,Interface * impl,fidl::InterfaceRequest<Interface> request)115   GattServerBase(bt::gatt::GATT::WeakPtr gatt,
116                  Interface* impl,
117                  fidl::InterfaceRequest<Interface> request)
118       : ServerBase<Interface>(impl, std::move(request)),
119         gatt_(std::move(gatt)) {
120     PW_DCHECK(gatt_.is_alive());
121   }
122 
123   ~GattServerBase() override = default;
124 
125  protected:
gatt()126   bt::gatt::GATT::WeakPtr gatt() const { return gatt_; }
127 
128  private:
129   bt::gatt::GATT::WeakPtr gatt_;
130 
131   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(GattServerBase);
132 };
133 
134 }  // namespace bthost
135