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 <string>
17 #include <vector>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/uuid.h"
20 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
21 
22 namespace bt {
23 
24 class ByteBuffer;
25 
26 namespace gap {
27 
28 class Peer;
29 
30 // A DiscoveryFilter allows clients of discovery procedures to filter results
31 // based on certain parameters, such as service UUIDs that might be present in
32 // EIR or advertising data, or based on available proximity information, to name
33 // a few.
34 class DiscoveryFilter final {
35  public:
36   DiscoveryFilter() = default;
37 
38   // Discovery filter based on the "Flags" bit field in LE Advertising Data. If
39   // |require_all| is true, then The filter is considered satisifed if ALL of
40   // the bits set in |flags_bitfield| are present in the advertisement.
41   // Otherwise, the filter is considered satisfied as long as one of the bits
42   // set in |flags_bitfield| is present.
43   void set_flags(uint8_t flags_bitfield, bool require_all = false) {
44     flags_ = flags_bitfield;
45     all_flags_required_ = require_all;
46   }
47 
48   // Discovery filter based on whether or not a device is connectable.
set_connectable(bool connectable)49   void set_connectable(bool connectable) { connectable_ = connectable; }
connectable()50   std::optional<bool> connectable() const { return connectable_; }
51 
52   // Sets the service UUIDs that should be present in a scan result. A scan
53   // result satisfies this filter if it provides at least one of the provided
54   // UUIDs.
55   //
56   // Passing an empty value for |service_uuids| effectively disables this
57   // filter.
set_service_uuids(const std::vector<UUID> & service_uuids)58   void set_service_uuids(const std::vector<UUID>& service_uuids) {
59     service_uuids_ = service_uuids;
60   }
service_uuids()61   const std::vector<UUID>& service_uuids() const { return service_uuids_; }
62 
63   // Filter on service data UUIDs.
64   //
65   // Passing an empty value for |service_data_uuids| effectively disables this
66   // filter.
set_service_data_uuids(const std::vector<UUID> & service_data_uuids)67   void set_service_data_uuids(const std::vector<UUID>& service_data_uuids) {
68     service_data_uuids_ = service_data_uuids;
69   }
service_data_uuids()70   const std::vector<UUID>& service_data_uuids() const {
71     return service_data_uuids_;
72   }
73 
74   // Sets a string to be matched against the device name. A scan result
75   // satisfies this filter if part of the complete or shortened device name
76   // fields matches |name_substring|.
77   //
78   // Passing an empty value for |name_substring| effectively disables this
79   // filter.
set_name_substring(const std::string & name_substring)80   void set_name_substring(const std::string& name_substring) {
81     name_substring_ = name_substring;
82   }
name_substring()83   const std::string& name_substring() const { return name_substring_; }
84 
85   // Sets a device to be filtered by the pathloss (in dBm) of the radio wave.
86   // This value is calculated using the received signal strength (measured
87   // locally) and the transmission power of the signal (as reported by the
88   // remote):
89   //
90   //   Path Loss = RSSI - Tx Power
91   //
92   // If this filter parameter has been set and the pathloss value calculated for
93   // a device greater than the provided |pathloss| value, then the scan result
94   // will fail to satisfy this filter.
95   //
96   // If this filter parameter has been set and the pathloss value cannot be
97   // calculated because the remote device did not report its transmission power,
98   // then the device will fail to satisfy this filter UNLESS an RSSI filter
99   // parameter has been set via SetRSSI() that is satisfied by the scan result.
set_pathloss(int8_t pathloss)100   void set_pathloss(int8_t pathloss) { pathloss_ = pathloss; }
pathloss()101   std::optional<int8_t> pathloss() const { return pathloss_; }
102 
103   // Sets a device to be filtered by RSSI. While this can produce inaccurate
104   // results when used alone to approximate proximity, it can still be useful
105   // when the scan results do not provide the remote device's Transmission
106   // Power.
107   //
108   // A remote device is considered to satisfy this filter parameter if the RSSI
109   // of the received transmission is greater than or equal to |rssi|, except if
110   // a path loss filter was provided via SetPathLoss() which the remote device
111   // failed to satisfy (see comments on SetPathLoss()).
set_rssi(int8_t rssi)112   void set_rssi(int8_t rssi) { rssi_ = rssi; }
113 
114   // Sets a device to be filtered by manufacturer specific data. A scan result
115   // satisfies this filter if it advertises manufacturer specific data
116   // containing |manufacturer_code|.
set_manufacturer_code(uint16_t manufacturer_code)117   void set_manufacturer_code(uint16_t manufacturer_code) {
118     manufacturer_code_ = manufacturer_code;
119   }
manufacturer_code()120   std::optional<uint16_t> manufacturer_code() const {
121     return manufacturer_code_;
122   }
123 
124   // Sets this filter up for the "General Discovery" procedure.
125   void SetGeneralDiscoveryFlags();
126 
127   // Returns true, if the given LE scan result satisfies this filter. Otherwise
128   // returns false. |advertising_data| should include scan response data, if
129   // any.
130   bool MatchLowEnergyResult(
131       const std::optional<std::reference_wrapper<const AdvertisingData>>
132           advertising_data,
133       bool connectable,
134       int8_t rssi) const;
135 
136   // Clears all the fields of this filter.
137   void Reset();
138 
139  private:
140   std::vector<UUID> service_uuids_;
141   std::vector<UUID> service_data_uuids_;
142   std::string name_substring_;
143   std::optional<uint8_t> flags_;
144   bool all_flags_required_;
145   std::optional<bool> connectable_;
146   std::optional<uint16_t> manufacturer_code_;
147   std::optional<int8_t> pathloss_;
148   std::optional<int8_t> rssi_;
149 };
150 
151 }  // namespace gap
152 }  // namespace bt
153