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