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