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 <fidl/fuchsia.hardware.bluetooth/cpp/fidl.h> 18 #include <lib/async/cpp/wait.h> 19 #include <lib/async/dispatcher.h> 20 #include <lib/zx/channel.h> 21 22 #include "pw_bluetooth/controller.h" 23 24 namespace bt::controllers { 25 26 class VendorEventHandler 27 : public fidl::AsyncEventHandler<fuchsia_hardware_bluetooth::Vendor> { 28 public: 29 explicit VendorEventHandler(std::function<void(zx_status_t)> unbind_callback); 30 void on_fidl_error(fidl::UnbindInfo error) override; 31 void handle_unknown_event( 32 fidl::UnknownEventMetadata<fuchsia_hardware_bluetooth::Vendor> metadata) 33 override; 34 35 private: 36 std::function<void(zx_status_t)> unbind_callback_; 37 }; 38 39 class HciEventHandler 40 : public fidl::AsyncEventHandler<fuchsia_hardware_bluetooth::HciTransport> { 41 public: 42 HciEventHandler( 43 std::function<void(zx_status_t)> unbind_callback, 44 std::function<void(fuchsia_hardware_bluetooth::ReceivedPacket)> 45 on_receive_callback); 46 void OnReceive(fuchsia_hardware_bluetooth::ReceivedPacket&) override; 47 void on_fidl_error(fidl::UnbindInfo error) override; 48 void handle_unknown_event( 49 fidl::UnknownEventMetadata<fuchsia_hardware_bluetooth::HciTransport> 50 metadata) override; 51 52 private: 53 std::function<void(fuchsia_hardware_bluetooth::ReceivedPacket)> 54 on_receive_callback_; 55 std::function<void(zx_status_t)> unbind_callback_; 56 }; 57 58 class FidlController final : public pw::bluetooth::Controller { 59 public: 60 using PwStatusCallback = pw::Callback<void(pw::Status)>; 61 62 // |dispatcher| must outlive this object. 63 FidlController( 64 fidl::ClientEnd<fuchsia_hardware_bluetooth::Vendor> vendor_client_end, 65 async_dispatcher_t* dispatcher); 66 67 ~FidlController() override; 68 69 // Controller overrides: SetEventFunction(DataFunction func)70 void SetEventFunction(DataFunction func) override { 71 event_cb_ = std::move(func); 72 } 73 SetReceiveAclFunction(DataFunction func)74 void SetReceiveAclFunction(DataFunction func) override { 75 acl_cb_ = std::move(func); 76 } 77 SetReceiveScoFunction(DataFunction func)78 void SetReceiveScoFunction(DataFunction func) override { 79 sco_cb_ = std::move(func); 80 } 81 SetReceiveIsoFunction(DataFunction func)82 void SetReceiveIsoFunction(DataFunction func) override { 83 iso_cb_ = std::move(func); 84 } 85 86 void Initialize(PwStatusCallback complete_callback, 87 PwStatusCallback error_callback) override; 88 89 void Close(PwStatusCallback callback) override; 90 91 void SendCommand(pw::span<const std::byte> command) override; 92 93 void SendAclData(pw::span<const std::byte> data) override; 94 95 void SendScoData(pw::span<const std::byte> data) override; 96 97 void SendIsoData(pw::span<const std::byte> data) override; 98 99 void ConfigureSco(ScoCodingFormat coding_format, 100 ScoEncoding encoding, 101 ScoSampleRate sample_rate, 102 pw::Callback<void(pw::Status)> callback) override; 103 104 void ResetSco(pw::Callback<void(pw::Status)> callback) override; 105 106 void GetFeatures(pw::Callback<void(FeaturesBits)> callback) override; 107 void EncodeVendorCommand( 108 pw::bluetooth::VendorCommandParameters parameters, 109 pw::Callback<void(pw::Result<pw::span<const std::byte>>)> callback) 110 override; 111 112 private: 113 class ScoEventHandler : public fidl::AsyncEventHandler< 114 fuchsia_hardware_bluetooth::ScoConnection> { 115 public: 116 ScoEventHandler(pw::Function<void(zx_status_t)> unbind_callback, 117 pw::Function<void(fuchsia_hardware_bluetooth::ScoPacket)> 118 on_receive_callback); 119 120 private: 121 // AsyncEventHandler<ScoConnection> overrides: 122 void OnReceive(fuchsia_hardware_bluetooth::ScoPacket& packet) override; 123 void on_fidl_error(fidl::UnbindInfo error) override; 124 void handle_unknown_event( 125 fidl::UnknownEventMetadata<fuchsia_hardware_bluetooth::ScoConnection> 126 metadata) override; 127 128 pw::Function<void(fuchsia_hardware_bluetooth::ScoPacket)> 129 on_receive_callback_; 130 pw::Function<void(zx_status_t)> unbind_callback_; 131 }; 132 133 void OnReceive(fuchsia_hardware_bluetooth::ReceivedPacket packet); 134 void OnReceiveSco(fuchsia_hardware_bluetooth::ScoPacket packet); 135 136 void OnScoUnbind(zx_status_t status); 137 138 // Cleanup and call |error_cb_| with |status| 139 void OnError(zx_status_t status); 140 141 void CleanUp(); 142 143 // Initializes HCI layer by binding |hci_handle| to |hci_| and opening two-way 144 // command channel and ACL data channel 145 void InitializeHci( 146 fidl::ClientEnd<fuchsia_hardware_bluetooth::HciTransport> hci_client_end); 147 148 // |vendor_handle_| holds the Vendor channel until Initialize() is called, at 149 // which point |vendor_| is bound to the channel. This prevents errors from 150 // being lost before initialization. 151 fidl::ClientEnd<fuchsia_hardware_bluetooth::Vendor> vendor_client_end_; 152 fidl::Client<fuchsia_hardware_bluetooth::Vendor> vendor_; 153 154 fidl::Client<fuchsia_hardware_bluetooth::HciTransport> hci_; 155 156 VendorEventHandler vendor_event_handler_; 157 HciEventHandler hci_event_handler_; 158 159 // Only set after ConfigureSco() is called. Unbound on ResetSco(). 160 std::optional<fidl::Client<fuchsia_hardware_bluetooth::ScoConnection>> 161 sco_connection_; 162 // Shared across all ScoConnections. 163 ScoEventHandler sco_event_handler_; 164 // Valid only when a ResetSco() call is pending. 165 PwStatusCallback reset_sco_cb_; 166 167 async_dispatcher_t* dispatcher_; 168 169 DataFunction event_cb_; 170 DataFunction acl_cb_; 171 DataFunction sco_cb_; 172 DataFunction iso_cb_; 173 PwStatusCallback initialize_complete_cb_; 174 PwStatusCallback error_cb_; 175 176 bool shutting_down_ = false; 177 }; 178 179 } // namespace bt::controllers 180