/* * Copyright 2021 HIMSA II K/S - www.himsa.com. * Represented by EHIMA - www.ehima.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include "base/functional/callback.h" #include "broadcaster_types.h" #include "bta_le_audio_broadcaster_api.h" #include "main/shim/le_advertising_manager.h" namespace { template class StateMachine { public: StateMachine() : state_(std::numeric_limits::min()) {} protected: StateT GetState() const { return state_; } void SetState(StateT state) { if (state < S) state_ = state; } private: StateT state_; }; } /* namespace */ /* Broadcast Stream state machine possible states: * Stopped - No broadcast Audio Stream is being transmitted. * Configuring- Configuration process was started. * Configured - The Broadcast Source has configured its controller for the * broadcast Audio Stream using implementation-specific * information or information provided by a higher-layer * specification. It advertises the information to allow * Broadcast Sinks and Scan Offloaders to detect the Audio Stream * and transmits extended advertisements that contain Broadcast * Audio Announcements, which associate periodic advertising * trains with broadcast Audio Streams, and transmits periodic * advertising trains. The periodic advertising trains carry * Basic Audio Announcements that contain the broadcast Audio * Stream parameters and metadata. No Audio Data packets are sent * over the air from the Broadcast Source in this state. The * periodic advertising trains do not carry the BIGInfo data * required to synchronize to broadcast Audio Streams. * Stopping - Broadcast Audio stream and advertisements are being stopped. * Streaming - The broadcast Audio Stream is enabled on the Broadcast Source, * allowing audio packets to be transmitted. The Broadcast Source * transmits extended advertisements that contain Broadcast Audio * Announcements, which associate periodic advertising trains with * the broadcast Audio Stream. The Broadcast Source also transmits * Basic Audio Announcements that contain broadcast Audio Stream * parameters and metadata and the BIGInfo data required for * synchronization to the broadcast Audio Stream by using periodic * advertisements while transmitting the broadcast Audio Stream. * The Broadcast Source may also transmit control parameters in * control packets within the broadcast Audio Stream. */ namespace bluetooth::le_audio { namespace broadcaster { class IBroadcastStateMachineCallbacks; struct BigConfig { uint8_t status; uint8_t big_id; uint32_t big_sync_delay; uint32_t transport_latency_big; uint8_t phy; uint8_t nse; uint8_t bn; uint8_t pto; uint8_t irc; uint16_t max_pdu; uint16_t iso_interval; std::vector connection_handles; }; struct BroadcastStateMachineConfig { bool is_public; bluetooth::le_audio::BroadcastId broadcast_id; std::string broadcast_name; uint8_t streaming_phy; BroadcastConfiguration config; bluetooth::le_audio::PublicBroadcastAnnouncementData public_announcement; bluetooth::le_audio::BasicAudioAnnouncementData announcement; std::optional broadcast_code; }; class BroadcastStateMachine : public StateMachine<5> { public: static constexpr uint8_t kAdvSidUndefined = 0xFF; static constexpr uint8_t kPaIntervalMax = 0xA0; /* 160 * 0.625 = 100ms */ static constexpr uint8_t kPaIntervalMin = 0x50; /* 80 * 0.625 = 50ms */ // LEA broadcast assigned register id, use positive number 0x1 // this should not matter since // le_advertising_manager will maintain the reg_id together with client_id // and java/jni is using negative number static constexpr uint8_t kLeAudioBroadcastRegId = 0x1; // Matching the ADDRESS_TYPE_* enums from Java // ADDRESS_TYPE_RANDOM_NON_RESOLVABLE = 2 static constexpr int8_t kBroadcastAdvertisingType = 0x2; static void Initialize(IBroadcastStateMachineCallbacks*, AdvertisingCallbacks* adv_callbacks); static std::unique_ptr CreateInstance( BroadcastStateMachineConfig msg); enum class Message : uint8_t { START = 0, SUSPEND, STOP, }; static const std::underlying_type::type MESSAGE_COUNT = static_cast::type>(Message::STOP) + 1; enum class State : uint8_t { STOPPED = 0, CONFIGURING, CONFIGURED, STOPPING, STREAMING, }; static const std::underlying_type::type STATE_COUNT = static_cast::type>(State::STREAMING) + 1; inline State GetState(void) const { return static_cast(StateMachine::GetState()); } virtual uint8_t GetAdvertisingSid() const { return advertising_sid_; } virtual uint8_t GetPaInterval() const { return kPaIntervalMax; } virtual bool Initialize() = 0; virtual const std::vector& GetCodecConfig() const = 0; virtual const BroadcastConfiguration& GetBroadcastConfig() const = 0; virtual std::optional const& GetBigConfig() const = 0; virtual BroadcastStateMachineConfig const& GetStateMachineConfig() const = 0; virtual void RequestOwnAddress( base::Callback cb) = 0; virtual void RequestOwnAddress() = 0; virtual RawAddress GetOwnAddress() = 0; virtual uint8_t GetOwnAddressType() = 0; virtual std::optional GetBroadcastCode() const = 0; virtual bluetooth::le_audio::BroadcastId GetBroadcastId() const = 0; virtual const bluetooth::le_audio::BasicAudioAnnouncementData& GetBroadcastAnnouncement() const = 0; virtual void UpdateBroadcastAnnouncement( bluetooth::le_audio::BasicAudioAnnouncementData announcement) = 0; virtual bool IsPublicBroadcast() = 0; virtual std::string GetBroadcastName() = 0; virtual const bluetooth::le_audio::PublicBroadcastAnnouncementData& GetPublicBroadcastAnnouncement() const = 0; virtual void UpdatePublicBroadcastAnnouncement( uint32_t broadcast_id, const std::string& broadcast_name, const bluetooth::le_audio::PublicBroadcastAnnouncementData& announcement) = 0; virtual void OnCreateAnnouncement(uint8_t advertising_sid, int8_t tx_power, uint8_t status) = 0; virtual void OnEnableAnnouncement(bool enable, uint8_t status) = 0; void SetMuted(bool muted) { is_muted_ = muted; }; bool IsMuted() const { return is_muted_; }; virtual void HandleHciEvent(uint16_t event, void* data) = 0; virtual void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle) = 0; virtual void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle) = 0; virtual void ProcessMessage(Message event, const void* data = nullptr) = 0; virtual ~BroadcastStateMachine() {} protected: BroadcastStateMachine() = default; void SetState(State state) { StateMachine::SetState( static_cast::type>(state)); } uint8_t advertising_sid_ = kAdvSidUndefined; bool is_muted_ = false; RawAddress addr_ = RawAddress::kEmpty; uint8_t addr_type_ = 0; }; class IBroadcastStateMachineCallbacks { public: IBroadcastStateMachineCallbacks() = default; virtual ~IBroadcastStateMachineCallbacks() = default; virtual void OnStateMachineCreateStatus(uint32_t broadcast_id, bool initialized) = 0; virtual void OnStateMachineDestroyed(uint32_t broadcast_id) = 0; virtual void OnStateMachineEvent(uint32_t broadcast_id, BroadcastStateMachine::State state, const void* data = nullptr) = 0; virtual void OnOwnAddressResponse(uint32_t broadcast_id, uint8_t addr_type, RawAddress address) = 0; virtual void OnBigCreated(const std::vector& conn_handle) = 0; }; std::ostream& operator<<( std::ostream& os, const bluetooth::le_audio::broadcaster::BroadcastStateMachine::Message& state); std::ostream& operator<<( std::ostream& os, const bluetooth::le_audio::broadcaster::BroadcastStateMachine::State& state); std::ostream& operator<<( std::ostream& os, const bluetooth::le_audio::broadcaster::BroadcastStateMachine& machine); std::ostream& operator<<( std::ostream& os, const bluetooth::le_audio::broadcaster::BigConfig& machine); std::ostream& operator<<( std::ostream& os, const bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig& machine); } /* namespace broadcaster */ } // namespace bluetooth::le_audio