MYNEWT-842 BLE Host - Stop GAP, add to rslv list

If an attempt to add a peer's IRK to the resolving list fails, the
failure is not reported, and the operation is not reattempted. Adding to
the resolving list fails if the host is scanning or advertising at the
time, so this is a common occurrence.

This commit address this problem as follows.  Before attempting to add
an entry to the resolving list, the host stops all active GAP
procedures.  After the entry has been successfully added, the
application must restart interrupted procedures as needed.

Interrupted procedures are reported with a reason or status code of
`BLE_HS_EPREEMPTED`.  Furthermore, an attempt to initiate a new GAP
procedure during preemption fails with a return code of
`BLE_HS_EPREEMPTED`.

There is one additional requirement which complicates this feature:
interrupted procedures must not be reported until after preemption has
ended.  That way, the application can restart the procedure immediately
upon receiving the event.  This requirement implies a somewhat strange
order of events when an entry is added to the resolving list:

1. Set the preempted state.
2. Abort all GAP procedures, but don't report anything.
3. Add the entry to the resolving list.
4. Clear the preempted state.
5. Finally, report interrupted procedures.

The implementation is further complicated by the nature of the
'cancel-create-connection' HCI exchange.  The cancel operation can be
considered complete as soon as the command-complete event is received,
but it does not get reported until the subsequent
'le-connection-complete' event is received.  For this reason, the GAP
must stay in the preempted state indefinitely until the expected event
is received.

X-Original-Commit: 76bfc3ba0d85ab591c97ba54728d5c3fa0669b57
This commit is contained in:
Christopher Collins
2017-10-17 13:07:15 -07:00
parent a16e7a2971
commit 2daa87d6dd
3 changed files with 45 additions and 20 deletions
+1
View File
@@ -631,6 +631,7 @@ ble_hs_init(void)
/* These get initialized here to allow unit tests to run without a zeroed
* bss.
*/
ble_hs_reset_reason = 0;
ble_hs_ev_tx_notifications = (struct os_event) {
.ev_cb = ble_hs_event_tx_notify,
};
+44 -9
View File
@@ -106,16 +106,15 @@ ble_hs_pvcy_clear_entries(void)
return 0;
}
int
ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addr_type,
const uint8_t *irk)
static int
ble_hs_pvcy_add_entry_hci(const uint8_t *addr, uint8_t addr_type,
const uint8_t *irk)
{
struct hci_add_dev_to_resolving_list add;
uint8_t buf[BLE_HCI_ADD_TO_RESOLV_LIST_LEN];
ble_addr_t peer_addr;
int rc;
STATS_INC(ble_hs_stats, pvcy_add_entry);
add.addr_type = addr_type;
memcpy(add.addr, addr, 6);
memcpy(add.local_irk, ble_hs_pvcy_irk, 16);
@@ -123,20 +122,56 @@ ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addr_type,
rc = ble_hs_hci_cmd_build_add_to_resolv_list(&add, buf, sizeof(buf));
if (rc != 0) {
goto err;
return rc;
}
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
buf, sizeof(buf), NULL, 0, NULL);
if (rc != 0) {
goto err;
return rc;
}
/* FIXME Controller is BT5.0 and default privacy mode is network which
* can cause problems for apps which are not aware of it. We need to
* sort it out somehow. For now we set device mode for all of the peer
* devices and application should change it to network if needed
*/
peer_addr.type = addr_type;
memcpy(peer_addr.val, addr, sizeof peer_addr.val);
rc = ble_hs_pvcy_set_mode(&peer_addr, BLE_GAP_PRIVATE_MODE_DEVICE);
if (rc != 0) {
return rc;
}
return 0;
}
int
ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addr_type,
const uint8_t *irk)
{
int rc;
STATS_INC(ble_hs_stats, pvcy_add_entry);
/* No GAP procedures can be active when adding an entry to the resolving
* list (Vol 2, Part E, 7.8.38). Stop all GAP procedures and temporarily
* prevent any new ones from being started.
*/
ble_gap_preempt();
/* Try to add the entry now that GAP is halted. */
rc = ble_hs_pvcy_add_entry_hci(addr, addr_type, irk);
/* Allow GAP procedures to be started again. */
ble_gap_preempt_done();
if (rc != 0) {
STATS_INC(ble_hs_stats, pvcy_add_entry_fail);
}
err:
STATS_INC(ble_hs_stats, pvcy_add_entry_fail);
return rc;
}
-11
View File
@@ -244,17 +244,6 @@ ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec)
if (rc != 0) {
return rc;
}
/* FIXME Controller is BT5.0 and default privacy mode is network which
* can cause problems for apps which are not aware of it. We need to
* sort it out somehow. For now we set device mode for all of the peer
* devices and application should change it to network if needed
*/
rc = ble_hs_pvcy_set_mode(&value_sec->peer_addr,
BLE_GAP_PRIVATE_MODE_DEVICE);
if (rc != 0) {
return rc;
}
}
return 0;