blob: b3a40ce067d2e3e5c3d161c0f990720957a1d404 [file] [log] [blame]
/*
* 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 <array>
#include <limits>
#include <optional>
#include <type_traits>
#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 <int S, typename StateT = uint8_t>
class StateMachine {
public:
StateMachine() : state_(std::numeric_limits<StateT>::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 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<uint16_t> connection_handles;
};
struct BroadcastStateMachineConfig {
bool is_public;
bluetooth::le_audio::BroadcastId broadcast_id;
std::string broadcast_name;
uint8_t streaming_phy;
BroadcastCodecWrapper codec_wrapper;
BroadcastQosConfig qos_config;
bluetooth::le_audio::PublicBroadcastAnnouncementData public_announcement;
bluetooth::le_audio::BasicAudioAnnouncementData announcement;
std::optional<bluetooth::le_audio::BroadcastCode> 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<BroadcastStateMachine> CreateInstance(
BroadcastStateMachineConfig msg);
enum class Message : uint8_t {
START = 0,
SUSPEND,
STOP,
};
static const std::underlying_type<Message>::type MESSAGE_COUNT =
static_cast<std::underlying_type<Message>::type>(Message::STOP) + 1;
enum class State : uint8_t {
STOPPED = 0,
CONFIGURING,
CONFIGURED,
STOPPING,
STREAMING,
};
static const std::underlying_type<State>::type STATE_COUNT =
static_cast<std::underlying_type<State>::type>(State::STREAMING) + 1;
inline State GetState(void) const {
return static_cast<State>(StateMachine::GetState());
}
virtual uint8_t GetAdvertisingSid() const { return advertising_sid_; }
virtual uint8_t GetPaInterval() const { return kPaIntervalMax; }
virtual bool Initialize() = 0;
virtual const BroadcastCodecWrapper& GetCodecConfig() const = 0;
virtual std::optional<BigConfig> const& GetBigConfig() const = 0;
virtual BroadcastStateMachineConfig const& GetStateMachineConfig() const = 0;
virtual void RequestOwnAddress(
base::Callback<void(uint8_t /* address_type*/, RawAddress /*address*/)>
cb) = 0;
virtual void RequestOwnAddress() = 0;
virtual RawAddress GetOwnAddress() = 0;
virtual uint8_t GetOwnAddressType() = 0;
virtual std::optional<bluetooth::le_audio::BroadcastCode> 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<std::underlying_type<State>::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<uint16_t>& conn_handle) = 0;
};
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastStateMachine::Message& state);
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastStateMachine::State& state);
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastStateMachine& machine);
std::ostream& operator<<(std::ostream& os,
const le_audio::broadcaster::BigConfig& machine);
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastStateMachineConfig& machine);
} /* namespace broadcaster */
} /* namespace le_audio */