hci: remove device from resolving list before adding it again for new pairing

This commit is contained in:
Matthias Ringwald 2020-09-16 17:14:59 +02:00
parent a108abeaf9
commit 02b02cffc7
3 changed files with 62 additions and 13 deletions

View File

@ -1319,15 +1319,23 @@ static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
}
// if not found, add to db
bool new_to_le_device_db = false;
if (le_db_index < 0) {
le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
#ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
hci_load_le_device_db_entry_into_resolving_list(le_db_index);
#endif
new_to_le_device_db = true;
}
if (le_db_index >= 0){
#ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
if (!new_to_le_device_db){
hci_remove_le_device_db_entry_from_resolving_list(le_db_index);
}
hci_load_le_device_db_entry_into_resolving_list(le_db_index);
#else
UNUSED(new_to_le_device_db);
#endif
sm_notify_client_index(SM_EVENT_IDENTITY_CREATED, sm_conn->sm_handle, setup->sm_peer_addr_type, setup->sm_peer_address, le_db_index);
sm_conn->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;

View File

@ -3838,16 +3838,36 @@ static bool hci_run_general_gap_le(void){
hci_send_cmd(&hci_le_read_resolving_list_size);
return true;
case LE_RESOLVING_LIST_SEND_CLEAR:
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_ADD_ENTRIES;
(void) memset(hci_stack->le_resolving_list_entries, 0xff, sizeof(hci_stack->le_resolving_list_entries));
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_REMOVE_ENTRIES;
(void) memset(hci_stack->le_resolving_list_add_entries, 0xff, sizeof(hci_stack->le_resolving_list_add_entries));
(void) memset(hci_stack->le_resolving_list_remove_entries, 0, sizeof(hci_stack->le_resolving_list_remove_entries));
hci_send_cmd(&hci_le_clear_resolving_list);
return true;
case LE_RESOLVING_LIST_ADD_ENTRIES:
case LE_RESOLVING_LIST_REMOVE_ENTRIES:
for (i = 0 ; i < MAX_NUM_RESOLVING_LIST_ENTRIES && i < le_device_db_max_count(); i++){
uint8_t offset = i >> 3;
uint8_t mask = 1 << (i & 7);
if ((hci_stack->le_resolving_list_remove_entries[offset] & mask) == 0) continue;
hci_stack->le_resolving_list_remove_entries[offset] &= ~mask;
bd_addr_t peer_identity_addreses;
int peer_identity_addr_type = (int) BD_ADDR_TYPE_UNKNOWN;
sm_key_t peer_irk;
le_device_db_info(i, &peer_identity_addr_type, peer_identity_addreses, peer_irk);
if (peer_identity_addr_type == BD_ADDR_TYPE_UNKNOWN) continue;
hci_send_cmd(&hci_le_remove_device_from_resolving_list, peer_identity_addr_type, peer_identity_addreses);
return true;
}
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_ADD_ENTRIES;
/* fall through */
case LE_RESOLVING_LIST_ADD_ENTRIES:
for (i = 0 ; i < MAX_NUM_RESOLVING_LIST_ENTRIES && i < le_device_db_max_count(); i++){
uint8_t offset = i >> 3;
uint8_t mask = 1 << (i & 7);
if ((hci_stack->le_resolving_list_entries[offset] & mask) == 0) continue;
hci_stack->le_resolving_list_entries[offset] &= ~mask;
if ((hci_stack->le_resolving_list_add_entries[offset] & mask) == 0) continue;
hci_stack->le_resolving_list_add_entries[offset] &= ~mask;
bd_addr_t peer_identity_addreses;
int peer_identity_addr_type = (int) BD_ADDR_TYPE_UNKNOWN;
sm_key_t peer_irk;
@ -3862,8 +3882,10 @@ static bool hci_run_general_gap_le(void){
hci_send_cmd(&hci_le_add_device_to_resolving_list, peer_identity_addr_type, peer_identity_addreses, peer_irk_flipped, local_irk_flipped);
return true;
}
break;
default:
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_DONE;
break;
default:
break;
}
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_DONE;
@ -5949,12 +5971,24 @@ void hci_load_le_device_db_entry_into_resolving_list(uint16_t le_device_db_index
if (le_device_db_index >= le_device_db_max_count()) return;
uint8_t offset = le_device_db_index >> 3;
uint8_t mask = 1 << (le_device_db_index & 7);
hci_stack->le_resolving_list_entries[offset] |= mask;
hci_stack->le_resolving_list_add_entries[offset] |= mask;
if (hci_stack->le_resolving_list_state == LE_RESOLVING_LIST_DONE){
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_ADD_ENTRIES;
// note: go back to remove entries, otherwise, a remove + add will skip the add
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_REMOVE_ENTRIES;
}
}
void hci_remove_le_device_db_entry_from_resolving_list(uint16_t le_device_db_index){
if (le_device_db_index >= MAX_NUM_RESOLVING_LIST_ENTRIES) return;
if (le_device_db_index >= le_device_db_max_count()) return;
uint8_t offset = le_device_db_index >> 3;
uint8_t mask = 1 << (le_device_db_index & 7);
hci_stack->le_resolving_list_remove_entries[offset] |= mask;
if (hci_stack->le_resolving_list_state == LE_RESOLVING_LIST_DONE){
hci_stack->le_resolving_list_state = LE_RESOLVING_LIST_REMOVE_ENTRIES;
}
}
uint8_t gap_load_resolving_list_from_le_device_db(void){
if ((hci_stack->local_supported_commands[1] & (1 << 2)) == 0) {
return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;

View File

@ -736,6 +736,7 @@ typedef enum {
LE_RESOLVING_LIST_SEND_ENABLE_ADDRESS_RESOLUTION,
LE_RESOLVING_LIST_READ_SIZE,
LE_RESOLVING_LIST_SEND_CLEAR,
LE_RESOLVING_LIST_REMOVE_ENTRIES,
LE_RESOLVING_LIST_ADD_ENTRIES,
LE_RESOLVING_LIST_DONE
} le_resolving_list_state_t;
@ -971,7 +972,8 @@ typedef struct {
#ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
le_resolving_list_state_t le_resolving_list_state;
uint16_t le_resolving_list_size;
uint8_t le_resolving_list_entries[ (MAX_NUM_RESOLVING_LIST_ENTRIES+7) / 8];
uint8_t le_resolving_list_add_entries[(MAX_NUM_RESOLVING_LIST_ENTRIES + 7) / 8];
uint8_t le_resolving_list_remove_entries[(MAX_NUM_RESOLVING_LIST_ENTRIES + 7) / 8];
#endif
} hci_stack_t;
@ -1271,6 +1273,11 @@ void hci_le_set_own_address_type(uint8_t own_address_type);
*/
void hci_load_le_device_db_entry_into_resolving_list(uint16_t le_device_db_index);
/**
* @note internal use by sm
*/
void hci_remove_le_device_db_entry_from_resolving_list(uint16_t le_device_db_index);
/**
* @brief Get Manufactured
* @return manufacturer id