• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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