1 // Copyright 2023 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 #include <pw_bluetooth/hci_android.emb.h> 17 18 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h" 19 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h" 20 #include "pw_bluetooth_sapphire/internal/host/transport/error.h" 21 22 namespace bt::l2cap { 23 24 namespace android_emb = pw::bluetooth::vendor::android_hci; 25 26 // Provides an API surface to start and stop A2DP offloading. A2dpOffloadManager 27 // tracks the state of A2DP offloading and allows at most one channel to be 28 // offloaded at a given time 29 class A2dpOffloadManager { 30 public: 31 // Configuration received from the profile server that needs to be converted 32 // to a command packet in order to send the StartA2dpOffload command 33 struct Configuration { 34 android_emb::A2dpCodecType codec; 35 uint16_t max_latency; 36 StaticPacket<android_emb::A2dpScmsTEnableWriter> scms_t_enable; 37 android_emb::A2dpSamplingFrequency sampling_frequency; 38 android_emb::A2dpBitsPerSample bits_per_sample; 39 android_emb::A2dpChannelMode channel_mode; 40 uint32_t encoded_audio_bit_rate; 41 42 StaticPacket<android_emb::SbcCodecInformationWriter> sbc_configuration; 43 StaticPacket<android_emb::AacCodecInformationWriter> aac_configuration; 44 StaticPacket<android_emb::LdacCodecInformationWriter> ldac_configuration; 45 StaticPacket<android_emb::AptxCodecInformationWriter> aptx_configuration; 46 }; 47 A2dpOffloadManager(hci::CommandChannel::WeakPtr cmd_channel)48 explicit A2dpOffloadManager(hci::CommandChannel::WeakPtr cmd_channel) 49 : cmd_channel_(std::move(cmd_channel)) {} 50 51 // Request the start of A2DP source offloading. |callback| will be called with 52 // the result of the request. If offloading is already started or still 53 // starting/stopping, the request will fail and |kInProgress| error will be 54 // reported synchronously. 55 void StartA2dpOffload(const Configuration& config, 56 ChannelId local_id, 57 ChannelId remote_id, 58 hci_spec::ConnectionHandle link_handle, 59 uint16_t max_tx_sdu_size, 60 hci::ResultCallback<> callback); 61 62 // Request the stop of A2DP source offloading on a specific channel. 63 // |callback| will be called with the result of the request. 64 // If offloading was not started or the channel requested is not offloaded, 65 // report success. Returns kInProgress error if channel offloading is 66 // currently in the process of stopping. 67 void RequestStopA2dpOffload(ChannelId local_id, 68 hci_spec::ConnectionHandle link_handle, 69 hci::ResultCallback<> callback); 70 71 // Returns true if channel with |id| and |link_handle| is starting/has started 72 // A2DP offloading 73 bool IsChannelOffloaded(ChannelId id, 74 hci_spec::ConnectionHandle link_handle) const; 75 GetWeakPtr()76 WeakPtr<A2dpOffloadManager> GetWeakPtr() { return weak_self_.GetWeakPtr(); } 77 78 private: 79 hci::CommandChannel::WeakPtr cmd_channel_; 80 81 A2dpOffloadStatus a2dp_offload_status_ = A2dpOffloadStatus::kStopped; 82 83 // Identifier for offloaded channel's endpoint on this device 84 std::optional<ChannelId> offloaded_channel_id_; 85 86 // Connection handle of the offloaded channel's underlying logical link 87 std::optional<hci_spec::ConnectionHandle> offloaded_link_handle_; 88 89 // Contains a callback if stop command was requested before offload status was 90 // |kStarted| 91 std::optional<hci::ResultCallback<>> pending_stop_a2dp_offload_request_; 92 93 WeakSelf<A2dpOffloadManager> weak_self_{this}; 94 }; 95 96 } // namespace bt::l2cap 97