1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <chrono>
20 #include <cstdint>
21 #include <optional>
22 #include <ratio>
23 #include <vector>
24 
25 #include "hci/address.h"
26 #include "hci/address_with_type.h"
27 #include "packets/hci_packets.h"
28 
29 namespace rootcanal {
30 
31 // Duration type for slots (increments of 625us).
32 using slots = std::chrono::duration<unsigned long long, std::ratio<625, 1000000>>;
33 
34 // User defined literal for slots, e.g. `0x800_slots`
35 slots operator"" _slots(unsigned long long count);
36 
37 using namespace bluetooth::hci;
38 
39 // Advertising interface common to legacy and extended advertisers.
40 class Advertiser {
41 public:
42   Advertiser() = default;
43   ~Advertiser() = default;
44 
IsEnabled()45   bool IsEnabled() const { return advertising_enable; }
Disable()46   void Disable() { advertising_enable = false; }
47 
GetAdvertisingAddress()48   AddressWithType GetAdvertisingAddress() const { return advertising_address; }
GetTargetAddress()49   AddressWithType GetTargetAddress() const { return target_address; }
50 
51   // HCI properties.
52   bool advertising_enable{false};
53   AddressWithType advertising_address{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
54   AddressWithType target_address{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
55 
56   // Time keeping.
57   std::chrono::steady_clock::time_point next_event{};
58   std::optional<std::chrono::steady_clock::time_point> timeout{};
59 };
60 
61 // Implement the unique legacy advertising instance.
62 // For extended advertising check the ExtendedAdvertiser class.
63 class LegacyAdvertiser : public Advertiser {
64 public:
65   LegacyAdvertiser() = default;
66   ~LegacyAdvertiser() = default;
67 
IsScannable()68   bool IsScannable() const {
69     return advertising_type != AdvertisingType::ADV_NONCONN_IND &&
70            advertising_type != AdvertisingType::ADV_DIRECT_IND_HIGH &&
71            advertising_type != AdvertisingType::ADV_DIRECT_IND_LOW;
72   }
73 
IsConnectable()74   bool IsConnectable() const {
75     return advertising_type != AdvertisingType::ADV_NONCONN_IND &&
76            advertising_type != AdvertisingType::ADV_SCAN_IND;
77   }
78 
IsDirected()79   bool IsDirected() const {
80     return advertising_type == AdvertisingType::ADV_DIRECT_IND_HIGH ||
81            advertising_type == AdvertisingType::ADV_DIRECT_IND_LOW;
82   }
83 
84   // Host configuration parameters. Gather the configuration from the
85   // legacy advertising HCI commands. The initial configuration
86   // matches the default values of the parameters of the HCI command
87   // LE Set Advertising Parameters.
88   slots advertising_interval{0x0800};
89   AdvertisingType advertising_type{AdvertisingType::ADV_IND};
90   OwnAddressType own_address_type{OwnAddressType::PUBLIC_DEVICE_ADDRESS};
91   PeerAddressType peer_address_type{PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS};
92   Address peer_address{};
93   uint8_t advertising_channel_map{0x07};
94   AdvertisingFilterPolicy advertising_filter_policy{AdvertisingFilterPolicy::ALL_DEVICES};
95   std::vector<uint8_t> advertising_data{};
96   std::vector<uint8_t> scan_response_data{};
97 };
98 
99 // Implement a single extended advertising set.
100 // The configuration is set by the extended advertising commands;
101 // for the legacy advertiser check the LegacyAdvertiser class.
102 class ExtendedAdvertiser : public Advertiser {
103 public:
advertising_handle(advertising_handle)104   ExtendedAdvertiser(uint8_t advertising_handle = 0) : advertising_handle(advertising_handle) {}
105   ~ExtendedAdvertiser() = default;
106 
Enable()107   void Enable() {
108     advertising_enable = true;
109     periodic_advertising_enable_latch = periodic_advertising_enable;
110     next_event = std::chrono::steady_clock::now();
111   }
112 
EnablePeriodic()113   void EnablePeriodic() {
114     periodic_advertising_enable = true;
115     periodic_advertising_enable_latch = advertising_enable;
116     next_periodic_event = std::chrono::steady_clock::now();
117   }
118 
DisablePeriodic()119   void DisablePeriodic() {
120     periodic_advertising_enable = false;
121     periodic_advertising_enable_latch = false;
122   }
123 
IsPeriodicEnabled()124   bool IsPeriodicEnabled() const { return periodic_advertising_enable_latch; }
IsScannable()125   bool IsScannable() const { return advertising_event_properties.scannable_; }
126 
IsConnectable()127   bool IsConnectable() const { return advertising_event_properties.connectable_; }
128 
IsDirected()129   bool IsDirected() const { return advertising_event_properties.directed_; }
130 
131   // Host configuration parameters. Gather the configuration from the
132   // extended advertising HCI commands.
133   uint8_t advertising_handle;
134   AdvertisingEventProperties advertising_event_properties{};
135   slots primary_advertising_interval{};
136   uint8_t primary_advertising_channel_map{};
137   OwnAddressType own_address_type{};
138   PeerAddressType peer_address_type{};
139   Address peer_address{};
140   std::optional<Address> random_address{};
141   AdvertisingFilterPolicy advertising_filter_policy{};
142   uint8_t advertising_tx_power{};
143   PrimaryPhyType primary_advertising_phy{};
144   uint8_t secondary_max_skip{};
145   SecondaryPhyType secondary_advertising_phy{};
146   uint8_t advertising_sid{};
147   bool scan_request_notification_enable{};
148   std::vector<uint8_t> advertising_data{};
149   std::vector<uint8_t> scan_response_data{};
150   bool partial_advertising_data{false};
151   bool partial_scan_response_data{false};
152 
153   // Periodic advertising configuration.
154   // Note: the enable flag has a latch because of the semantic describe in the
155   // specification:
156   //
157   // If the advertising set is not currently enabled, the periodic advertising
158   // is not started until the advertising set is enabled. Once the advertising
159   // set has been enabled, the Controller shall continue periodic advertising
160   // until the Host issues an HCI_LE_Set_Periodic_Advertising_Enable command
161   // with bit 0 of Enable set to 0 (periodic advertising is disabled).
162   // Disabling the advertising set has no effect on the periodic advertising
163   // once the advertising set has been enabled.
164   //
165   // Thus the enable latch is set when the advertising set is enabled and
166   // periodic advertising is enabled, and cleared when periodic advertising
167   // gets disabled.
168   bool periodic_advertising_enable{false};
169   bool periodic_advertising_enable_latch{false};
170   slots periodic_advertising_interval{};
171   std::vector<uint8_t> periodic_advertising_data{};
172   bool partial_periodic_advertising_data{false};
173 
174   // Time keeping for periodic advertising.
175   std::chrono::steady_clock::time_point next_periodic_event{};
176 
177   // Enabled state.
178   uint8_t max_extended_advertising_events{0};
179   uint8_t num_completed_extended_advertising_events{0};
180 
181   // Not implemented at the moment.
182   bool constant_tone_extensions{false};
183 
184   // Compute the maximum advertising data payload size for the selected
185   // advertising event properties. The advertising data is not present if
186   // 0 is returned.
187   static uint16_t GetMaxAdvertisingDataLength(const AdvertisingEventProperties& properties);
188 
189   // Compute the maximum scan response data payload size for the selected
190   // advertising event properties. The scan response data is not present if
191   // 0 is returned.
192   static uint16_t GetMaxScanResponseDataLength(const AdvertisingEventProperties& properties);
193 
194   // Reconstitute the raw Advertising_Event_Properties bitmask.
195   static uint16_t GetRawAdvertisingEventProperties(const AdvertisingEventProperties& properties);
196 
197   // Compute the maximum periodic advertising data payload size for the
198   // selected periodic advertising interval.
199   static uint16_t GetMaxPeriodicAdvertisingDataLength(slots periodic_advertising_interval);
200 };
201 
202 }  // namespace rootcanal
203