1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License") {
5 
6  }
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <algorithm>
20 #include <cstdint>
21 
22 #include "log.h"
23 #include "model/controller/link_layer_controller.h"
24 #include "packets/hci_packets.h"
25 
26 #pragma GCC diagnostic ignored "-Wunused-parameter"
27 
28 namespace rootcanal::apcf {
29 
HasFilterIndex(uint8_t apcf_filter_index) const30 bool ApcfScanner::HasFilterIndex(uint8_t apcf_filter_index) const {
31   return std::any_of(std::begin(filters), std::end(filters), [&](auto it) {
32     return it.filter_index == apcf_filter_index;
33   });
34 }
35 
ClearFilterIndex(uint8_t apcf_filter_index)36 void ApcfScanner::ClearFilterIndex(uint8_t apcf_filter_index) {
37   broadcaster_address_filters.erase(
38       std::remove_if(
39           std::begin(broadcaster_address_filters),
40           std::end(broadcaster_address_filters),
41           [&](auto it) { return it.filter_index == apcf_filter_index; }),
42       std::end(broadcaster_address_filters));
43   service_uuid_filters.erase(
44       std::remove_if(
45           std::begin(service_uuid_filters), std::end(service_uuid_filters),
46           [&](auto it) { return it.filter_index == apcf_filter_index; }),
47       std::end(service_uuid_filters));
48   service_solicitation_uuid_filters.erase(
49       std::remove_if(
50           std::begin(service_solicitation_uuid_filters),
51           std::end(service_solicitation_uuid_filters),
52           [&](auto it) { return it.filter_index == apcf_filter_index; }),
53       std::end(service_solicitation_uuid_filters));
54   local_name_filters.erase(
55       std::remove_if(
56           std::begin(local_name_filters), std::end(local_name_filters),
57           [&](auto it) { return it.filter_index == apcf_filter_index; }),
58       std::end(local_name_filters));
59   manufacturer_data_filters.erase(
60       std::remove_if(
61           std::begin(manufacturer_data_filters),
62           std::end(manufacturer_data_filters),
63           [&](auto it) { return it.filter_index == apcf_filter_index; }),
64       std::end(manufacturer_data_filters));
65   service_data_filters.erase(
66       std::remove_if(
67           std::begin(service_data_filters), std::end(service_data_filters),
68           [&](auto it) { return it.filter_index == apcf_filter_index; }),
69       std::end(service_data_filters));
70   ad_type_filters.erase(
71       std::remove_if(
72           std::begin(ad_type_filters), std::end(ad_type_filters),
73           [&](auto it) { return it.filter_index == apcf_filter_index; }),
74       std::end(ad_type_filters));
75 }
76 
Clear()77 void ApcfScanner::Clear() {
78   filters.clear();
79   broadcaster_address_filters.clear();
80   service_uuid_filters.clear();
81   service_solicitation_uuid_filters.clear();
82   local_name_filters.clear();
83   manufacturer_data_filters.clear();
84   service_data_filters.clear();
85   ad_type_filters.clear();
86 }
87 
88 template <typename T>
UpdateFilterList(std::vector<T> & filter_list,size_t max_filter_list_size,bluetooth::hci::ApcfAction action,T filter)89 ErrorCode ApcfScanner::UpdateFilterList(std::vector<T>& filter_list,
90                                         size_t max_filter_list_size,
91                                         bluetooth::hci::ApcfAction action,
92                                         T filter) {
93   if (!HasFilterIndex(filter.filter_index)) {
94     return ErrorCode::UNKNOWN_CONNECTION;
95   }
96 
97   switch (action) {
98     case ApcfAction::ADD: {
99       if (filter_list.size() == max_filter_list_size) {
100         return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
101       }
102 
103       filter_list.emplace_back(std::move(filter));
104       return ErrorCode::SUCCESS;
105     }
106     case ApcfAction::DELETE: {
107       // Delete will delete the specified data in the specified filter.
108       filter_list.erase(
109           std::remove_if(std::begin(filter_list), std::end(filter_list),
110                          [&](auto it) { return it == filter; }),
111           std::end(filter_list));
112       return ErrorCode::SUCCESS;
113     }
114     case ApcfAction::CLEAR: {
115       // Clear will clear all data in the specified filter.
116       filter_list.erase(
117           std::remove_if(
118               std::begin(filter_list), std::end(filter_list),
119               [&](auto it) { return it.filter_index == filter.filter_index; }),
120           std::end(filter_list));
121       return ErrorCode::SUCCESS;
122     }
123     default:
124       break;
125   }
126 
127   return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
128 }
129 
operator ==(BroadcasterAddressFilter const & lhs,BroadcasterAddressFilter const & rhs)130 bool operator==(BroadcasterAddressFilter const& lhs,
131                 BroadcasterAddressFilter const& rhs) {
132   return lhs.filter_index == rhs.filter_index &&
133          lhs.broadcaster_address == rhs.broadcaster_address &&
134          lhs.application_address_type == rhs.application_address_type;
135 }
136 
operator ==(GapDataFilter const & lhs,GapDataFilter const & rhs)137 bool operator==(GapDataFilter const& lhs, GapDataFilter const& rhs) {
138   return lhs.filter_index == rhs.filter_index && lhs.gap_data == rhs.gap_data &&
139          lhs.gap_data_mask == rhs.gap_data_mask;
140 }
141 
operator ==(AdTypeFilter const & lhs,AdTypeFilter const & rhs)142 bool operator==(AdTypeFilter const& lhs, AdTypeFilter const& rhs) {
143   return lhs.filter_index == rhs.filter_index && lhs.ad_type == rhs.ad_type &&
144          lhs.ad_data == rhs.ad_data && lhs.ad_data_mask == rhs.ad_data_mask;
145 }
146 
147 }  // namespace rootcanal::apcf
148 
149 namespace rootcanal {
150 
151 using bluetooth::hci::ApcfAction;
152 
LeApcfEnable(bool apcf_enable)153 ErrorCode LinkLayerController::LeApcfEnable(bool apcf_enable) {
154   apcf_scanner_.enable = apcf_enable;
155   return ErrorCode::SUCCESS;
156 }
157 
LeApcfAddFilteringParameters(uint8_t apcf_filter_index,uint16_t apcf_feature_selection,uint16_t apcf_list_logic_type,uint8_t apcf_filter_logic_type,uint8_t rssi_high_thresh,bluetooth::hci::DeliveryMode delivery_mode,uint16_t onfound_timeout,uint8_t onfound_timeout_cnt,uint8_t rssi_low_thresh,uint16_t onlost_timeout,uint16_t num_of_tracking_entries,uint8_t * apcf_available_spaces)158 ErrorCode LinkLayerController::LeApcfAddFilteringParameters(
159     uint8_t apcf_filter_index, uint16_t apcf_feature_selection,
160     uint16_t apcf_list_logic_type, uint8_t apcf_filter_logic_type,
161     uint8_t rssi_high_thresh, bluetooth::hci::DeliveryMode delivery_mode,
162     uint16_t onfound_timeout, uint8_t onfound_timeout_cnt,
163     uint8_t rssi_low_thresh, uint16_t onlost_timeout,
164     uint16_t num_of_tracking_entries, uint8_t* apcf_available_spaces) {
165   *apcf_available_spaces =
166       properties_.le_apcf_filter_list_size - apcf_scanner_.filters.size();
167 
168       if (apcf_scanner_.HasFilterIndex(apcf_filter_index)) {
169         INFO(id_, "apcf filter index {} already configured", apcf_filter_index);
170         return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
171       }
172 
173       if (*apcf_available_spaces == 0) {
174         INFO(id_, "reached max number of apcf filters");
175         return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
176       }
177 
178       apcf_scanner_.filters.push_back(rootcanal::apcf::Filter{
179           .filter_index = apcf_filter_index,
180           .feature_selection = apcf_feature_selection,
181           .list_logic_type = apcf_list_logic_type,
182           .filter_logic_type = apcf_filter_logic_type,
183           .rssi_high_thresh = rssi_high_thresh,
184           .delivery_mode = delivery_mode,
185           .onfound_timeout = onfound_timeout,
186           .onfound_timeout_cnt = onfound_timeout_cnt,
187           .rssi_low_thresh = rssi_low_thresh,
188           .onlost_timeout = onlost_timeout,
189           .num_of_tracking_entries = num_of_tracking_entries,
190       });
191 
192       *apcf_available_spaces -= 1;
193       return ErrorCode::SUCCESS;
194 }
195 
LeApcfDeleteFilteringParameters(uint8_t apcf_filter_index,uint8_t * apcf_available_spaces)196 ErrorCode LinkLayerController::LeApcfDeleteFilteringParameters(
197     uint8_t apcf_filter_index, uint8_t* apcf_available_spaces) {
198       *apcf_available_spaces =
199           properties_.le_apcf_filter_list_size - apcf_scanner_.filters.size();
200 
201       if (!apcf_scanner_.HasFilterIndex(apcf_filter_index)) {
202         INFO(id_, "apcf filter index {} is not configured", apcf_filter_index);
203         return ErrorCode::UNKNOWN_CONNECTION;
204       }
205 
206       apcf_scanner_.filters.erase(
207           std::remove_if(
208               std::begin(apcf_scanner_.filters),
209               std::end(apcf_scanner_.filters),
210               [&](auto it) { return it.filter_index == apcf_filter_index; }),
211           std::end(apcf_scanner_.filters));
212 
213       apcf_scanner_.ClearFilterIndex(apcf_filter_index);
214       *apcf_available_spaces += 1;
215       return ErrorCode::SUCCESS;
216 }
217 
LeApcfClearFilteringParameters(uint8_t * apcf_available_spaces)218 ErrorCode LinkLayerController::LeApcfClearFilteringParameters(
219     uint8_t* apcf_available_spaces) {
220       apcf_scanner_.Clear();
221       *apcf_available_spaces = properties_.le_apcf_filter_list_size;
222       return ErrorCode::SUCCESS;
223 }
224 
LeApcfBroadcasterAddress(ApcfAction apcf_action,uint8_t apcf_filter_index,bluetooth::hci::Address apcf_broadcaster_address,bluetooth::hci::ApcfApplicationAddressType apcf_application_address_type,uint8_t * apcf_available_spaces)225 ErrorCode LinkLayerController::LeApcfBroadcasterAddress(
226     ApcfAction apcf_action, uint8_t apcf_filter_index,
227     bluetooth::hci::Address apcf_broadcaster_address,
228     bluetooth::hci::ApcfApplicationAddressType apcf_application_address_type,
229     uint8_t* apcf_available_spaces) {
230   ErrorCode status = apcf_scanner_.UpdateFilterList(
231       apcf_scanner_.broadcaster_address_filters,
232       properties_.le_apcf_broadcaster_address_filter_list_size, apcf_action,
233       rootcanal::apcf::BroadcasterAddressFilter{
234           .filter_index = apcf_filter_index,
235           .broadcaster_address = apcf_broadcaster_address,
236           .application_address_type = apcf_application_address_type,
237       });
238 
239   *apcf_available_spaces =
240       properties_.le_apcf_broadcaster_address_filter_list_size -
241       apcf_scanner_.broadcaster_address_filters.size();
242 
243   return status;
244 }
245 
LeApcfServiceUuid(ApcfAction apcf_action,uint8_t apcf_filter_index,std::vector<uint8_t> apcf_uuid_data,uint8_t * apcf_available_spaces)246 ErrorCode LinkLayerController::LeApcfServiceUuid(
247     ApcfAction apcf_action, uint8_t apcf_filter_index,
248     std::vector<uint8_t> apcf_uuid_data, uint8_t* apcf_available_spaces) {
249   size_t uuid_data_size = apcf_uuid_data.size() / 2;
250   std::vector<uint8_t> uuid_data(std::begin(apcf_uuid_data),
251                                  std::begin(apcf_uuid_data) + uuid_data_size);
252   std::vector<uint8_t> uuid_data_mask(
253       std::begin(apcf_uuid_data) + uuid_data_size, std::end(apcf_uuid_data));
254 
255   ErrorCode status = apcf_scanner_.UpdateFilterList(
256       apcf_scanner_.service_uuid_filters,
257       properties_.le_apcf_service_uuid_filter_list_size, apcf_action,
258       rootcanal::apcf::GapDataFilter{
259           .filter_index = apcf_filter_index,
260           .gap_data = uuid_data,
261           .gap_data_mask = uuid_data_mask,
262       });
263 
264   *apcf_available_spaces = properties_.le_apcf_service_uuid_filter_list_size -
265                            apcf_scanner_.service_uuid_filters.size();
266 
267   return status;
268 }
269 
LeApcfServiceSolicitationUuid(ApcfAction apcf_action,uint8_t apcf_filter_index,std::vector<uint8_t> apcf_uuid_data,uint8_t * apcf_available_spaces)270 ErrorCode LinkLayerController::LeApcfServiceSolicitationUuid(
271     ApcfAction apcf_action, uint8_t apcf_filter_index,
272     std::vector<uint8_t> apcf_uuid_data, uint8_t* apcf_available_spaces) {
273   size_t uuid_data_size = apcf_uuid_data.size() / 2;
274   std::vector<uint8_t> uuid_data(std::begin(apcf_uuid_data),
275                                  std::begin(apcf_uuid_data) + uuid_data_size);
276   std::vector<uint8_t> uuid_data_mask(
277       std::begin(apcf_uuid_data) + uuid_data_size, std::end(apcf_uuid_data));
278 
279   ErrorCode status = apcf_scanner_.UpdateFilterList(
280       apcf_scanner_.service_solicitation_uuid_filters,
281       properties_.le_apcf_service_solicitation_uuid_filter_list_size,
282       apcf_action,
283       rootcanal::apcf::GapDataFilter{
284           .filter_index = apcf_filter_index,
285           .gap_data = uuid_data,
286           .gap_data_mask = uuid_data_mask,
287       });
288 
289   *apcf_available_spaces =
290       properties_.le_apcf_service_solicitation_uuid_filter_list_size -
291       apcf_scanner_.service_solicitation_uuid_filters.size();
292 
293   return status;
294 }
295 
LeApcfLocalName(ApcfAction apcf_action,uint8_t apcf_filter_index,std::vector<uint8_t> apcf_local_name,uint8_t * apcf_available_spaces)296 ErrorCode LinkLayerController::LeApcfLocalName(
297     ApcfAction apcf_action, uint8_t apcf_filter_index,
298     std::vector<uint8_t> apcf_local_name, uint8_t* apcf_available_spaces) {
299   size_t local_name_size = apcf_local_name.size() / 2;
300   std::vector<uint8_t> local_name(
301       std::begin(apcf_local_name),
302       std::begin(apcf_local_name) + local_name_size);
303   std::vector<uint8_t> local_name_mask(
304       std::begin(apcf_local_name) + local_name_size, std::end(apcf_local_name));
305 
306   ErrorCode status = apcf_scanner_.UpdateFilterList(
307       apcf_scanner_.local_name_filters,
308       properties_.le_apcf_local_name_filter_list_size, apcf_action,
309       rootcanal::apcf::GapDataFilter{
310           .filter_index = apcf_filter_index,
311           .gap_data = local_name,
312           .gap_data_mask = local_name_mask,
313       });
314 
315   *apcf_available_spaces = properties_.le_apcf_local_name_filter_list_size -
316                            apcf_scanner_.local_name_filters.size();
317 
318   return status;
319 }
320 
LeApcfManufacturerData(ApcfAction apcf_action,uint8_t apcf_filter_index,std::vector<uint8_t> apcf_manufacturer_data,uint8_t * apcf_available_spaces)321 ErrorCode LinkLayerController::LeApcfManufacturerData(
322     ApcfAction apcf_action, uint8_t apcf_filter_index,
323     std::vector<uint8_t> apcf_manufacturer_data,
324     uint8_t* apcf_available_spaces) {
325   size_t manufacturer_data_size = apcf_manufacturer_data.size() / 2;
326   std::vector<uint8_t> manufacturer_data(
327       std::begin(apcf_manufacturer_data),
328       std::begin(apcf_manufacturer_data) + manufacturer_data_size);
329   std::vector<uint8_t> manufacturer_data_mask(
330       std::begin(apcf_manufacturer_data) + manufacturer_data_size,
331       std::end(apcf_manufacturer_data));
332 
333   ErrorCode status = apcf_scanner_.UpdateFilterList(
334       apcf_scanner_.manufacturer_data_filters,
335       properties_.le_apcf_manufacturer_data_filter_list_size, apcf_action,
336       rootcanal::apcf::GapDataFilter{
337           .filter_index = apcf_filter_index,
338           .gap_data = manufacturer_data,
339           .gap_data_mask = manufacturer_data_mask,
340       });
341 
342   *apcf_available_spaces =
343       properties_.le_apcf_manufacturer_data_filter_list_size -
344       apcf_scanner_.manufacturer_data_filters.size();
345 
346   return status;
347 }
348 
LeApcfServiceData(ApcfAction apcf_action,uint8_t apcf_filter_index,std::vector<uint8_t> apcf_service_data,uint8_t * apcf_available_spaces)349 ErrorCode LinkLayerController::LeApcfServiceData(
350     ApcfAction apcf_action, uint8_t apcf_filter_index,
351     std::vector<uint8_t> apcf_service_data, uint8_t* apcf_available_spaces) {
352   size_t service_data_size = apcf_service_data.size() / 2;
353   std::vector<uint8_t> service_data(
354       std::begin(apcf_service_data),
355       std::begin(apcf_service_data) + service_data_size);
356   std::vector<uint8_t> service_data_mask(
357       std::begin(apcf_service_data) + service_data_size,
358       std::end(apcf_service_data));
359 
360   ErrorCode status = apcf_scanner_.UpdateFilterList(
361       apcf_scanner_.service_data_filters,
362       properties_.le_apcf_service_data_filter_list_size, apcf_action,
363       rootcanal::apcf::GapDataFilter{
364           .filter_index = apcf_filter_index,
365           .gap_data = service_data,
366           .gap_data_mask = service_data_mask,
367       });
368 
369   *apcf_available_spaces = properties_.le_apcf_service_data_filter_list_size -
370                            apcf_scanner_.service_data_filters.size();
371 
372   return status;
373 }
374 
LeApcfAdTypeFilter(ApcfAction apcf_action,uint8_t apcf_filter_index,uint8_t apcf_ad_type,std::vector<uint8_t> apcf_ad_data,std::vector<uint8_t> apcf_ad_data_mask,uint8_t * apcf_available_spaces)375 ErrorCode LinkLayerController::LeApcfAdTypeFilter(
376     ApcfAction apcf_action, uint8_t apcf_filter_index, uint8_t apcf_ad_type,
377     std::vector<uint8_t> apcf_ad_data, std::vector<uint8_t> apcf_ad_data_mask,
378     uint8_t* apcf_available_spaces) {
379   ErrorCode status = apcf_scanner_.UpdateFilterList(
380       apcf_scanner_.ad_type_filters,
381       properties_.le_apcf_ad_type_filter_list_size, apcf_action,
382       rootcanal::apcf::AdTypeFilter{
383           .filter_index = apcf_filter_index,
384           .ad_type = apcf_ad_type,
385           .ad_data = std::move(apcf_ad_data),
386           .ad_data_mask = std::move(apcf_ad_data_mask),
387       });
388 
389   *apcf_available_spaces = properties_.le_apcf_ad_type_filter_list_size -
390                            apcf_scanner_.ad_type_filters.size();
391 
392   return status;
393 }
394 
395 }  // namespace rootcanal
396