1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains functions for BLE whitelist operation.
22 *
23 ******************************************************************************/
24
25 #include <base/logging.h>
26 #include <unordered_map>
27
28 #include "bt_types.h"
29 #include "btm_int.h"
30 #include "btu.h"
31 #include "device/include/controller.h"
32 #include "hcimsgs.h"
33 #include "l2c_int.h"
34
35 extern void btm_send_hci_create_connection(
36 uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy,
37 uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own,
38 uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency,
39 uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len,
40 uint8_t phy);
41 extern void btm_ble_create_conn_cancel();
42
43 // Unfortunately (for now?) we have to maintain a copy of the device whitelist
44 // on the host to determine if a device is pending to be connected or not. This
45 // controls whether the host should keep trying to scan for whitelisted
46 // peripherals or not.
47 // TODO: Move all of this to controller/le/background_list or similar?
48 struct BackgroundConnection {
49 RawAddress address;
50 uint8_t addr_type;
51 bool in_controller_wl;
52 uint8_t addr_type_in_wl;
53 bool pending_removal;
54 };
55
56 struct BgConnHash {
operator ()BgConnHash57 std::size_t operator()(const RawAddress& x) const {
58 const uint8_t* a = x.address;
59 return a[0] ^ (a[1] << 8) ^ (a[2] << 16) ^ (a[3] << 24) ^ a[4] ^
60 (a[5] << 8);
61 }
62 };
63
64 static std::unordered_map<RawAddress, BackgroundConnection, BgConnHash>
65 background_connections;
66
background_connection_add(uint8_t addr_type,const RawAddress & address)67 static void background_connection_add(uint8_t addr_type,
68 const RawAddress& address) {
69 auto map_iter = background_connections.find(address);
70 if (map_iter == background_connections.end()) {
71 background_connections[address] =
72 BackgroundConnection{address, addr_type, false, 0, false};
73 } else {
74 BackgroundConnection* connection = &map_iter->second;
75 connection->addr_type = addr_type;
76 connection->pending_removal = false;
77 }
78 }
79
background_connection_remove(const RawAddress & address)80 static void background_connection_remove(const RawAddress& address) {
81 auto map_iter = background_connections.find(address);
82 if (map_iter != background_connections.end()) {
83 if (map_iter->second.in_controller_wl) {
84 map_iter->second.pending_removal = true;
85 } else {
86 background_connections.erase(map_iter);
87 }
88 }
89 }
90
background_connections_clear()91 static void background_connections_clear() { background_connections.clear(); }
92
background_connections_pending()93 static bool background_connections_pending() {
94 for (auto& map_el : background_connections) {
95 BackgroundConnection* connection = &map_el.second;
96 if (connection->pending_removal) continue;
97 const bool connected =
98 BTM_IsAclConnectionUp(connection->address, BT_TRANSPORT_LE);
99 if (!connected) {
100 return true;
101 }
102 }
103 return false;
104 }
105
background_connections_count()106 static int background_connections_count() {
107 int count = 0;
108 for (auto& map_el : background_connections) {
109 if (!map_el.second.pending_removal) ++count;
110 }
111 return count;
112 }
113
114 /*******************************************************************************
115 *
116 * Function btm_update_scanner_filter_policy
117 *
118 * Description This function updates the filter policy of scanner
119 ******************************************************************************/
btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy)120 void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) {
121 tBTM_BLE_INQ_CB* p_inq = &btm_cb.ble_ctr_cb.inq_var;
122
123 uint32_t scan_interval =
124 !p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval;
125 uint32_t scan_window =
126 !p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window;
127
128 BTM_TRACE_EVENT("%s", __func__);
129
130 p_inq->sfp = scan_policy;
131 p_inq->scan_type = p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE
132 ? BTM_BLE_SCAN_MODE_ACTI
133 : p_inq->scan_type;
134
135 btm_send_hci_set_scan_params(
136 p_inq->scan_type, (uint16_t)scan_interval, (uint16_t)scan_window,
137 btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, scan_policy);
138 }
139
140 /*******************************************************************************
141 *
142 * Function btm_ble_bgconn_cancel_if_disconnected
143 *
144 * Description If a device has been disconnected, it must be re-added to
145 * the white list. If needed, this function cancels a pending
146 * initiate command in order to trigger restart of the initiate
147 * command which in turn updates the white list.
148 *
149 * Parameters bd_addr: updated device
150 *
151 ******************************************************************************/
btm_ble_bgconn_cancel_if_disconnected(const RawAddress & bd_addr)152 void btm_ble_bgconn_cancel_if_disconnected(const RawAddress& bd_addr) {
153 if (btm_ble_get_conn_st() != BLE_CONNECTING) return;
154
155 auto map_it = background_connections.find(bd_addr);
156 if (map_it != background_connections.end()) {
157 BackgroundConnection* connection = &map_it->second;
158 if (!connection->in_controller_wl && !connection->pending_removal &&
159 !BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) {
160 btm_ble_stop_auto_conn();
161 }
162 }
163 }
164
BTM_BackgroundConnectAddressKnown(const RawAddress & address)165 bool BTM_BackgroundConnectAddressKnown(const RawAddress& address) {
166 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(address);
167
168 // not a known device, or a classic device, we assume public address
169 if (p_dev_rec == NULL || (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == 0)
170 return true;
171
172 // bonded device with identity address known
173 if (p_dev_rec->ble.identity_addr != address &&
174 !p_dev_rec->ble.identity_addr.IsEmpty()) {
175 return true;
176 }
177
178 // Public address, Random Static, or Random Non-Resolvable Address known
179 if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC ||
180 !BTM_BLE_IS_RESOLVE_BDA(address)) {
181 return true;
182 }
183
184 // Only Resolvable Private Address (RPA) is known, we don't allow it into
185 // the background connection procedure.
186 return false;
187 }
188
189 /*******************************************************************************
190 *
191 * Function btm_add_dev_to_controller
192 *
193 * Description This function load the device into controller white list
194 ******************************************************************************/
btm_add_dev_to_controller(bool to_add,const RawAddress & bd_addr)195 bool btm_add_dev_to_controller(bool to_add, const RawAddress& bd_addr) {
196 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
197
198 if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
199 if (to_add) {
200 if (p_dev_rec->ble.identity_addr != bd_addr &&
201 !p_dev_rec->ble.identity_addr.IsEmpty()) {
202 background_connection_add(p_dev_rec->ble.identity_addr_type,
203 p_dev_rec->ble.identity_addr);
204 } else {
205 background_connection_add(p_dev_rec->ble.ble_addr_type, bd_addr);
206
207 if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
208 BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
209 LOG(INFO) << __func__ << " addig RPA into white list";
210 }
211 }
212
213 p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
214 } else {
215 if (!p_dev_rec->ble.identity_addr.IsEmpty() &&
216 p_dev_rec->ble.identity_addr != bd_addr) {
217 background_connection_remove(p_dev_rec->ble.identity_addr);
218 } else {
219 background_connection_remove(bd_addr);
220
221 if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
222 BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
223 LOG(INFO) << __func__ << " removing RPA from white list";
224 }
225 }
226
227 p_dev_rec->ble.in_controller_list &= ~BTM_WHITE_LIST_BIT;
228 }
229 } else {
230 /* not a known device, i.e. attempt to connect to device never seen before
231 */
232 if (to_add)
233 background_connection_add(BLE_ADDR_PUBLIC, bd_addr);
234 else
235 background_connection_remove(bd_addr);
236 }
237
238 return true;
239 }
240
241 /** White list add complete */
wl_add_complete(uint8_t * p_data,uint16_t)242 void wl_add_complete(uint8_t* p_data, uint16_t /* evt_len */) {
243 uint8_t status;
244 STREAM_TO_UINT8(status, p_data);
245 VLOG(2) << __func__ << ": status=" << loghex(status);
246 }
247
248 /** White list element remove complete */
wl_remove_complete(uint8_t * p_data,uint16_t)249 void wl_remove_complete(uint8_t* p_data, uint16_t /* evt_len */) {
250 uint8_t status;
251 STREAM_TO_UINT8(status, p_data);
252 VLOG(2) << __func__ << ": status=" << loghex(status);
253 }
254
255 /*******************************************************************************
256 *
257 * Function btm_execute_wl_dev_operation
258 *
259 * Description execute the pending whitelist device operation (loading or
260 * removing)
261 ******************************************************************************/
btm_execute_wl_dev_operation(void)262 bool btm_execute_wl_dev_operation(void) {
263 // handle removals first to avoid filling up controller's white list
264 for (auto map_it = background_connections.begin();
265 map_it != background_connections.end();) {
266 BackgroundConnection* connection = &map_it->second;
267 if (connection->pending_removal) {
268 btsnd_hcic_ble_remove_from_white_list(
269 connection->addr_type_in_wl, connection->address,
270 base::BindOnce(&wl_remove_complete));
271 map_it = background_connections.erase(map_it);
272 } else
273 ++map_it;
274 }
275 for (auto& map_el : background_connections) {
276 BackgroundConnection* connection = &map_el.second;
277 const bool connected =
278 BTM_IsAclConnectionUp(connection->address, BT_TRANSPORT_LE);
279 if (!connection->in_controller_wl && !connected) {
280 btsnd_hcic_ble_add_white_list(connection->addr_type, connection->address,
281 base::BindOnce(&wl_add_complete));
282 connection->in_controller_wl = true;
283 connection->addr_type_in_wl = connection->addr_type;
284 } else if (connection->in_controller_wl && connected) {
285 /* Bluetooth Core 4.2 as well as ESR08 disallows more than one
286 connection between two LE addresses. Not all controllers handle this
287 correctly, therefore we must make sure connected devices are not in
288 the white list when bg connection attempt is active. */
289 btsnd_hcic_ble_remove_from_white_list(
290 connection->addr_type_in_wl, connection->address,
291 base::BindOnce(&wl_remove_complete));
292 connection->in_controller_wl = false;
293 }
294 }
295 return true;
296 }
297
298 /*******************************************************************************
299 *
300 * Function btm_ble_white_list_init
301 *
302 * Description Initialize white list size
303 *
304 ******************************************************************************/
btm_ble_white_list_init(uint8_t white_list_size)305 void btm_ble_white_list_init(uint8_t white_list_size) {
306 BTM_TRACE_DEBUG("%s white_list_size = %d", __func__, white_list_size);
307 }
308
BTM_SetLeConnectionModeToFast()309 bool BTM_SetLeConnectionModeToFast() {
310 VLOG(2) << __func__;
311 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
312 if ((p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF &&
313 p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ||
314 (p_cb->scan_int == BTM_BLE_SCAN_SLOW_INT_1 &&
315 p_cb->scan_win == BTM_BLE_SCAN_SLOW_WIN_1)) {
316 p_cb->scan_int = BTM_BLE_SCAN_FAST_INT;
317 p_cb->scan_win = BTM_BLE_SCAN_FAST_WIN;
318 return true;
319 }
320 return false;
321 }
322
BTM_SetLeConnectionModeToSlow()323 void BTM_SetLeConnectionModeToSlow() {
324 VLOG(2) << __func__;
325 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
326 if ((p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF &&
327 p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ||
328 (p_cb->scan_int == BTM_BLE_SCAN_FAST_INT &&
329 p_cb->scan_win == BTM_BLE_SCAN_FAST_WIN)) {
330 p_cb->scan_int = BTM_BLE_SCAN_SLOW_INT_1;
331 p_cb->scan_win = BTM_BLE_SCAN_SLOW_WIN_1;
332 }
333 }
334
335 /** This function is to start auto connection procedure */
btm_ble_start_auto_conn()336 bool btm_ble_start_auto_conn() {
337 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
338
339 BTM_TRACE_EVENT("%s", __func__);
340
341 uint16_t scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF)
342 ? BTM_BLE_SCAN_SLOW_INT_1
343 : p_cb->scan_int;
344 uint16_t scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF)
345 ? BTM_BLE_SCAN_SLOW_WIN_1
346 : p_cb->scan_win;
347 uint8_t own_addr_type = p_cb->addr_mgnt_cb.own_addr_type;
348 uint8_t peer_addr_type = BLE_ADDR_PUBLIC;
349
350 uint8_t phy = PHY_LE_1M;
351 if (controller_get_interface()->supports_ble_2m_phy()) phy |= PHY_LE_2M;
352 if (controller_get_interface()->supports_ble_coded_phy()) phy |= PHY_LE_CODED;
353
354 if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
355 LOG(INFO) << "initate background connection fail, topology limitation";
356 return false;
357 }
358
359 if (btm_ble_get_conn_st() != BLE_CONN_IDLE ||
360 !background_connections_pending() || !l2cu_can_allocate_lcb()) {
361 return false;
362 }
363
364 p_cb->wl_state |= BTM_BLE_WL_INIT;
365
366 btm_execute_wl_dev_operation();
367
368 #if (BLE_PRIVACY_SPT == TRUE)
369 btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_INIT);
370 if (btm_cb.ble_ctr_cb.rl_state != BTM_BLE_RL_IDLE &&
371 controller_get_interface()->supports_ble_privacy()) {
372 own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
373 peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
374 }
375 #endif
376
377 btm_send_hci_create_connection(
378 scan_int, /* uint16_t scan_int */
379 scan_win, /* uint16_t scan_win */
380 0x01, /* uint8_t white_list */
381 peer_addr_type, /* uint8_t addr_type_peer */
382 RawAddress::kEmpty, /* BD_ADDR bda_peer */
383 own_addr_type, /* uint8_t addr_type_own */
384 BTM_BLE_CONN_INT_MIN_DEF, /* uint16_t conn_int_min */
385 BTM_BLE_CONN_INT_MAX_DEF, /* uint16_t conn_int_max */
386 BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* uint16_t conn_latency */
387 BTM_BLE_CONN_TIMEOUT_DEF, /* uint16_t conn_timeout */
388 0, /* uint16_t min_len */
389 0, /* uint16_t max_len */
390 phy);
391 return true;
392 }
393
394 /** This function is to stop auto connection procedure */
btm_ble_stop_auto_conn()395 bool btm_ble_stop_auto_conn() {
396 BTM_TRACE_EVENT("%s", __func__);
397
398 if (btm_ble_get_conn_st() != BLE_CONNECTING) {
399 BTM_TRACE_DEBUG("conn_st = %d, not in auto conn state, cannot stop",
400 btm_ble_get_conn_st());
401 return false;
402 }
403
404 btm_ble_create_conn_cancel();
405
406 btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_INIT;
407 return true;
408 }
409
410 /*******************************************************************************
411 *
412 * Function btm_ble_suspend_bg_conn
413 *
414 * Description This function is to suspend an active background connection
415 * procedure.
416 *
417 * Parameters none.
418 *
419 * Returns none.
420 *
421 ******************************************************************************/
btm_ble_suspend_bg_conn(void)422 bool btm_ble_suspend_bg_conn(void) {
423 BTM_TRACE_EVENT("%s", __func__);
424 return btm_ble_stop_auto_conn();
425 }
426
427 /*******************************************************************************
428 *
429 * Function btm_ble_resume_bg_conn
430 *
431 * Description This function is to resume a background auto connection
432 * procedure.
433 *
434 * Parameters none.
435 *
436 * Returns none.
437 *
438 ******************************************************************************/
btm_ble_resume_bg_conn(void)439 bool btm_ble_resume_bg_conn(void) { return btm_ble_start_auto_conn(); }
440
441 /** Adds the device into white list. Returns false if white list is full and
442 * device can't be added, true otherwise. */
BTM_WhiteListAdd(const RawAddress & address)443 bool BTM_WhiteListAdd(const RawAddress& address) {
444 VLOG(1) << __func__ << ": " << address;
445
446 if (background_connections_count() ==
447 controller_get_interface()->get_ble_white_list_size()) {
448 BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__);
449 return false;
450 }
451
452 if (btm_cb.ble_ctr_cb.wl_state & BTM_BLE_WL_INIT) {
453 btm_ble_stop_auto_conn();
454 }
455 btm_add_dev_to_controller(true, address);
456 btm_ble_resume_bg_conn();
457 return true;
458 }
459
460 /** Removes the device from white list */
BTM_WhiteListRemove(const RawAddress & address)461 void BTM_WhiteListRemove(const RawAddress& address) {
462 VLOG(1) << __func__ << ": " << address;
463 if (btm_cb.ble_ctr_cb.wl_state & BTM_BLE_WL_INIT) {
464 btm_ble_stop_auto_conn();
465 }
466 btm_add_dev_to_controller(false, address);
467 btm_ble_resume_bg_conn();
468 }
469
470 /** clear white list complete */
wl_clear_complete(uint8_t * p_data,uint16_t)471 void wl_clear_complete(uint8_t* p_data, uint16_t /* evt_len */) {
472 uint8_t status;
473 STREAM_TO_UINT8(status, p_data);
474 VLOG(2) << __func__ << ": status=" << loghex(status);
475 }
476
477 /** Clear the whitelist, end any pending whitelist connections */
BTM_WhiteListClear()478 void BTM_WhiteListClear() {
479 VLOG(1) << __func__;
480 if (!controller_get_interface()->supports_ble()) return;
481 btm_ble_stop_auto_conn();
482 btsnd_hcic_ble_clear_white_list(base::BindOnce(&wl_clear_complete));
483 background_connections_clear();
484 }
485