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/hci/advertising_handle_map.h"
17 #include "pw_bluetooth_sapphire/internal/host/hci/low_energy_advertiser.h"
18 #include "pw_bluetooth_sapphire/internal/host/transport/transport.h"
19 
20 namespace bt::hci {
21 
22 class SequentialCommandRunner;
23 
24 class ExtendedLowEnergyAdvertiser final : public LowEnergyAdvertiser {
25  public:
26   explicit ExtendedLowEnergyAdvertiser(hci::Transport::WeakPtr hci,
27                                        uint16_t max_advertising_data_length_);
28   ~ExtendedLowEnergyAdvertiser() override;
29 
AllowsRandomAddressChange()30   bool AllowsRandomAddressChange() const override { return !IsAdvertising(); }
31 
32   // Attempt to start advertising. See LowEnergyAdvertiser::StartAdvertising for
33   // full documentation.
34   //
35   // According to the Bluetooth Spec, Volume 4, Part E, Section 7.8.58, "the
36   // number of advertising sets that can be supported is not fixed and the
37   // Controller can change it at any time. The memory used to store advertising
38   // sets can also be used for other purposes."
39   //
40   // This method may report an error if the controller cannot currently support
41   // another advertising set.
42   void StartAdvertising(const DeviceAddress& address,
43                         const AdvertisingData& data,
44                         const AdvertisingData& scan_rsp,
45                         const AdvertisingOptions& options,
46                         ConnectionCallback connect_callback,
47                         ResultFunction<> result_callback) override;
48 
49   void StopAdvertising() override;
50   void StopAdvertising(const DeviceAddress& address,
51                        bool extended_pdu) override;
52 
53   void OnIncomingConnection(
54       hci_spec::ConnectionHandle handle,
55       pw::bluetooth::emboss::ConnectionRole role,
56       const DeviceAddress& peer_address,
57       const hci_spec::LEConnectionParameters& conn_params) override;
58 
MaxAdvertisements()59   size_t MaxAdvertisements() const override {
60     return advertising_handle_map_.capacity();
61   }
62 
63   // Returns the last used advertising handle that was used for an advertising
64   // set when communicating with the controller.
LastUsedHandleForTesting()65   std::optional<hci_spec::AdvertisingHandle> LastUsedHandleForTesting() const {
66     return advertising_handle_map_.LastUsedHandleForTesting();
67   }
68 
69  private:
70   struct StagedConnectionParameters {
71     pw::bluetooth::emboss::ConnectionRole role;
72     DeviceAddress peer_address;
73     hci_spec::LEConnectionParameters conn_params;
74   };
75 
76   struct StagedAdvertisingParameters {
77     bool include_tx_power_level = false;
78     int8_t selected_tx_power_level = 0;
79     bool extended_pdu = false;
80 
clearStagedAdvertisingParameters81     void clear() {
82       include_tx_power_level = false;
83       selected_tx_power_level = 0;
84       extended_pdu = false;
85     }
86   };
87 
88   CommandPacket BuildEnablePacket(
89       const DeviceAddress& address,
90       pw::bluetooth::emboss::GenericEnableParam enable,
91       bool extended_pdu) override;
92 
93   std::optional<CommandPacket> BuildSetAdvertisingParams(
94       const DeviceAddress& address,
95       const AdvertisingEventProperties& properties,
96       pw::bluetooth::emboss::LEOwnAddressType own_address_type,
97       const AdvertisingIntervalRange& interval,
98       bool extended_pdu) override;
99 
100   std::vector<CommandPacket> BuildSetAdvertisingData(
101       const DeviceAddress& address,
102       const AdvertisingData& data,
103       AdvFlags flags,
104       bool extended_pdu) override;
105 
106   CommandPacket BuildUnsetAdvertisingData(const DeviceAddress& address,
107                                           bool extended_pdu) override;
108 
109   std::vector<CommandPacket> BuildSetScanResponse(const DeviceAddress& address,
110                                                   const AdvertisingData& data,
111                                                   bool extended_pdu) override;
112 
113   CommandPacket BuildUnsetScanResponse(const DeviceAddress& address,
114                                        bool extended_pdu) override;
115 
116   CommandPacket BuildRemoveAdvertisingSet(const DeviceAddress& address,
117                                           bool extended_pdu) override;
118 
119   CommandPacket BuildAdvertisingDataFragmentPacket(
120       hci_spec::AdvertisingHandle handle,
121       const BufferView& data,
122       pw::bluetooth::emboss::LESetExtendedAdvDataOp operation,
123       pw::bluetooth::emboss::LEExtendedAdvFragmentPreference
124           fragment_preference);
125 
126   CommandPacket BuildScanResponseDataFragmentPacket(
127       hci_spec::AdvertisingHandle handle,
128       const BufferView& data,
129       pw::bluetooth::emboss::LESetExtendedAdvDataOp operation,
130       pw::bluetooth::emboss::LEExtendedAdvFragmentPreference
131           fragment_preference);
132 
133   void OnSetAdvertisingParamsComplete(const EventPacket& event) override;
134 
135   void OnCurrentOperationComplete() override;
136 
137   // Event handler for the HCI LE Advertising Set Terminated event
138   void OnAdvertisingSetTerminatedEvent(const EventPacket& event);
139   CommandChannel::EventHandlerId event_handler_id_;
140 
141   AdvertisingHandleMap advertising_handle_map_;
142   std::queue<fit::closure> op_queue_;
143   StagedAdvertisingParameters staged_advertising_parameters_;
144 
145   // Core Spec Volume 4, Part E, Section 7.8.56: Incoming connections to LE
146   // Extended Advertising occur through two events: HCI_LE_Connection_Complete
147   // and HCI_LE_Advertising_Set_Terminated. The HCI_LE_Connection_Complete event
148   // provides the connection handle along with some other connection related
149   // parameters. Notably missing is the advertising handle, which we need to
150   // obtain the advertised device address. Until we receive the
151   // HCI_LE_Advertising_Set_Terminated event, we stage these parameters.
152   std::unordered_map<hci_spec::ConnectionHandle, StagedConnectionParameters>
153       staged_connections_;
154 
155   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ExtendedLowEnergyAdvertiser);
156 };
157 
158 }  // namespace bt::hci
159