| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_FIDL_PROFILE_SERVER_H_ |
| #define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_FIDL_PROFILE_SERVER_H_ |
| |
| #include <fuchsia/bluetooth/bredr/cpp/fidl.h> |
| |
| #include <fbl/macros.h> |
| |
| #include "lib/fidl/cpp/binding.h" |
| #include "src/connectivity/bluetooth/core/bt-host/fidl/server_base.h" |
| #include "src/connectivity/bluetooth/core/bt-host/gap/bredr_connection_manager.h" |
| #include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h" |
| #include "src/connectivity/bluetooth/core/bt-host/sdp/server.h" |
| #include "src/connectivity/bluetooth/core/bt-host/sdp/service_record.h" |
| #include "src/connectivity/bluetooth/core/bt-host/socket/socket_factory.h" |
| #include "src/lib/fxl/memory/weak_ptr.h" |
| |
| namespace bthost { |
| |
| // Implements the bredr::Profile FIDL interface. |
| class ProfileServer : public ServerBase<fuchsia::bluetooth::bredr::Profile> { |
| public: |
| ProfileServer(fxl::WeakPtr<bt::gap::Adapter> adapter, |
| fidl::InterfaceRequest<fuchsia::bluetooth::bredr::Profile> request); |
| ~ProfileServer() override; |
| |
| private: |
| class AudioDirectionExt; |
| |
| class L2capParametersExt final |
| : public ServerBase<fuchsia::bluetooth::bredr::L2capParametersExt> { |
| public: |
| L2capParametersExt( |
| fidl::InterfaceRequest<fuchsia::bluetooth::bredr::L2capParametersExt> request, |
| fbl::RefPtr<bt::l2cap::Channel> channel); |
| void RequestParameters(fuchsia::bluetooth::bredr::ChannelParameters requested, |
| RequestParametersCallback callback) override; |
| |
| private: |
| fbl::RefPtr<bt::l2cap::Channel> channel_; |
| }; |
| |
| struct ScoRequest : public fbl::RefCounted<ScoRequest> { |
| std::optional<bt::gap::BrEdrConnectionManager::ScoRequestHandle> request_handle; |
| fuchsia::bluetooth::bredr::ScoConnectionReceiverPtr receiver; |
| }; |
| |
| // fuchsia::bluetooth::bredr::Profile overrides: |
| void Advertise(std::vector<fuchsia::bluetooth::bredr::ServiceDefinition> definitions, |
| fuchsia::bluetooth::bredr::ChannelParameters parameters, |
| fidl::InterfaceHandle<fuchsia::bluetooth::bredr::ConnectionReceiver> receiver, |
| AdvertiseCallback callback) override; |
| void Search(fuchsia::bluetooth::bredr::ServiceClassProfileIdentifier service_uuid, |
| std::vector<uint16_t> attr_ids, |
| fidl::InterfaceHandle<fuchsia::bluetooth::bredr::SearchResults> results) override; |
| void Connect(fuchsia::bluetooth::PeerId peer_id, |
| fuchsia::bluetooth::bredr::ConnectParameters connection, |
| ConnectCallback callback) override; |
| void ConnectSco( |
| ::fuchsia::bluetooth::PeerId peer_id, bool initiator, |
| fuchsia::bluetooth::bredr::ScoConnectionParameters params, |
| fidl::InterfaceHandle<fuchsia::bluetooth::bredr::ScoConnectionReceiver> receiver) override; |
| |
| // Callback when clients close their connection targets |
| void OnConnectionReceiverError(uint64_t ad_id, zx_status_t status); |
| |
| // Callback when clients close their search results |
| void OnSearchResultError(uint64_t search_id, zx_status_t status); |
| |
| // Callback for incoming connections |
| void OnChannelConnected(uint64_t ad_id, fbl::RefPtr<bt::l2cap::Channel> channel, |
| const bt::sdp::DataElement& protocol_list); |
| |
| // Callback for services found on connected device |
| void OnServiceFound(uint64_t search_id, bt::PeerId peer_id, |
| const std::map<bt::sdp::AttributeId, bt::sdp::DataElement>& attributes); |
| |
| // Callback for SCO connections requests. |
| void OnScoConnectionResult(fbl::RefPtr<ScoRequest>, |
| bt::sco::ScoConnectionManager::ConnectionResult); |
| |
| // Callback when clients close their audio direction extension. |
| void OnAudioDirectionExtError(AudioDirectionExt* ext_server, zx_status_t status); |
| |
| // Create an AudioDirectionExt server for the given channel and set up callbacks. |
| // Returns the client end of the channel. |
| fidl::InterfaceHandle<fuchsia::bluetooth::bredr::AudioDirectionExt> BindAudioDirectionExtServer( |
| fbl::RefPtr<bt::l2cap::Channel> channel); |
| |
| // Callback when clients close their l2cap parameters extension. |
| void OnL2capParametersExtError(L2capParametersExt* ext_server, zx_status_t status); |
| |
| // Create an L2capParametersExt server for the given channel and set up callbacks. |
| // Returns the client end of the channel. |
| fidl::InterfaceHandle<fuchsia::bluetooth::bredr::L2capParametersExt> BindL2capParametersExtServer( |
| fbl::RefPtr<bt::l2cap::Channel> channel); |
| |
| // Create a FIDL Channel from an l2cap::Channel. A socket channel relay is created from |channel| |
| // and returned in the FIDL Channel. |
| fuchsia::bluetooth::bredr::Channel ChannelToFidl(fbl::RefPtr<bt::l2cap::Channel> channel); |
| |
| bt::gap::Adapter* adapter() const { return adapter_.get(); } |
| |
| // Advertised Services |
| struct AdvertisedService { |
| AdvertisedService(fidl::InterfacePtr<fuchsia::bluetooth::bredr::ConnectionReceiver> receiver, |
| bt::sdp::Server::RegistrationHandle registration_handle, |
| AdvertiseCallback disconnection_cb) |
| : receiver(std::move(receiver)), |
| registration_handle(registration_handle), |
| disconnection_cb(std::move(disconnection_cb)) {} |
| fidl::InterfacePtr<fuchsia::bluetooth::bredr::ConnectionReceiver> receiver; |
| bt::sdp::Server::RegistrationHandle registration_handle; |
| AdvertiseCallback disconnection_cb; |
| }; |
| |
| uint64_t advertised_total_; |
| std::map<uint64_t, AdvertisedService> current_advertised_; |
| |
| // Searches registered |
| struct RegisteredSearch { |
| RegisteredSearch(fidl::InterfacePtr<fuchsia::bluetooth::bredr::SearchResults> results, |
| bt::gap::BrEdrConnectionManager::SearchId search_id) |
| : results(std::move(results)), search_id(search_id) {} |
| fidl::InterfacePtr<fuchsia::bluetooth::bredr::SearchResults> results; |
| bt::gap::BrEdrConnectionManager::SearchId search_id; |
| }; |
| |
| uint64_t searches_total_; |
| std::map<uint64_t, RegisteredSearch> searches_; |
| |
| class AudioDirectionExt final : public ServerBase<fuchsia::bluetooth::bredr::AudioDirectionExt> { |
| public: |
| // Calls to SetPriority() are forwarded to |priority_cb|. |
| AudioDirectionExt(fidl::InterfaceRequest<fuchsia::bluetooth::bredr::AudioDirectionExt> request, |
| fbl::RefPtr<bt::l2cap::Channel> channel); |
| |
| // fuchsia::bluetooth::bredr::AudioDirectionExt overrides: |
| void SetPriority(fuchsia::bluetooth::bredr::A2dpDirectionPriority priority, |
| SetPriorityCallback callback) override; |
| |
| private: |
| fbl::RefPtr<bt::l2cap::Channel> channel_; |
| fit::function<void(fuchsia::bluetooth::bredr::A2dpDirectionPriority, SetPriorityCallback)> cb_; |
| }; |
| std::unordered_map<AudioDirectionExt*, std::unique_ptr<AudioDirectionExt>> |
| audio_direction_ext_servers_; |
| |
| std::unordered_map<L2capParametersExt*, std::unique_ptr<L2capParametersExt>> |
| l2cap_parameters_ext_servers_; |
| |
| fxl::WeakPtr<bt::gap::Adapter> adapter_; |
| |
| // Creates sockets that bridge L2CAP channels to profile processes. |
| bt::socket::SocketFactory<bt::l2cap::Channel> l2cap_socket_factory_; |
| |
| // Creates sockets that bridge SCO connections to profile processes. |
| bt::socket::SocketFactory<bt::sco::ScoConnection> sco_socket_factory_; |
| |
| // Keep this as the last member to make sure that all weak pointers are |
| // invalidated before other members get destroyed. |
| fxl::WeakPtrFactory<ProfileServer> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ProfileServer); |
| }; |
| |
| } // namespace bthost |
| |
| #endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_FIDL_PROFILE_SERVER_H_ |