mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-26 10:47:23 +00:00
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:
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user