Connection using old pairing information saved

I am running an experiment to use a static keys for pairing information without breaking the existing flow of pairing/bonding.
What I am doing is I am storing the pairing info of my central device and storing it into a structure and then erasing the flash to remove those information, and after reset I am retrieving those bonding information and connecting again using the same central devices but I am getting "Peer removed bonding info" response on my phone.

void store_ltk_in_zephyr(void)
{
    int id, err;
    struct bt_keys pairing_info = {
    .addr = {
        .type = BT_ADDR_LE_PUBLIC,
        .a.val = {0x43,0x82,0x5E,0xC7,0xE8,0xF4,0xFD}
    },
    .irk = {0x8A, 0x27, 0x1E, 0xA7, 0x92, 0x2A, 0xF0, 0x15, 0x41, 0x69, 0x48, 0xDD, 0xC0, 0x7E, 0xDD, 0xF7},
    .ltk = {
        .val = {0xc0, 0xe6, 0x9a, 0x0a, 0xf7, 0x4b, 0xdc, 0xb7, 0x7d, 0x23, 0xf4, 0xb4, 0x89, 0x8d, 0x96, 0x02},
        .ediv = {0x00,0x00},
        .rand = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
      }
    };

    // Store the keys using the settings API
    err = bt_keys_store(&pairing_info);
    if (err) {
        printk("Failed to store keys (err %d)\n", err);
    } else {
        printk("Keys stored successfully\n");
    }
}


In main, I am calling like this to load the info onto the flash- 

  settings_subsys_init();
  //smp_bt_register();
	bt_conn_auth_cb_register(&auth_cb_display);
  bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
	err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
    k_sleep(K_MSEC(100));
		err = bt_enable(NULL);                                      //Trying one more time after this system reset
    if(err) NVIC_SystemReset();
	}
  store_ltk_in_zephyr();
  if (IS_ENABLED(CONFIG_SETTINGS)) {
    settings_load();
  }


And on connect I am using like this-
  bt_conn_set_security(conn, BT_SECURITY_L1|BT_SECURITY_FORCE_PAIR);


Do let me know, how can I connect with the same bonding info which I have made a copy of from the same bonding structure.

  • This is what is known as attribute caching. Basically the attribute table from the previous application has been cached by the your GATT Client. About attribute caching from the Core spec:

    Did you existing nRF5 SDK based application include the Service Changed characteristic? In that case, you should be able to send a service changed indication to trigger the client to perform a new service discovery. 

  • Did you existing nRF5 SDK based application include the Service Changed characteristic? In that case, you should be able to send a service changed indication to trigger the client to perform a new service discovery. 

    Yes we have one.
    What is the API for indicating the service change, I didn`t find any online and have enabled the CONFIG_BT_GATT_SERVICE_CHANGED=y also.

  •  I have implemented this part too but nRF Connect application on iOS is not changing the discovery

    static void sc_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
    {
        bool notif_enabled = (value == BT_GATT_CCC_NOTIFY);
        printk("Service Changed notifications %s\n", notif_enabled ? "enabled" : "disabled");
    }
    
    BT_GATT_SERVICE_DEFINE(sc_svc,
        BT_GATT_PRIMARY_SERVICE(BT_UUID_GATT),
        BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SC, BT_GATT_CHRC_INDICATE, BT_GATT_PERM_NONE,
                               NULL, NULL, sc_value),
        BT_GATT_CCC(sc_ccc_cfg_changed,BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
    );
    
    void notify_service_changed(struct bt_conn *conn)
    {
        //struct bt_conn *conn = NULL;  // Update this to point to the correct connection if needed
        uint16_t start_handle = 0x0001; // Start handle of the affected range
        uint16_t end_handle = 0xFFFF;   // End handle of the affected range
    
        sc_value[0] = start_handle & 0xFF;
        sc_value[1] = (start_handle >> 8) & 0xFF;
        sc_value[2] = end_handle & 0xFF;
        sc_value[3] = (end_handle >> 8) & 0xFF;
    
        int err = bt_gatt_notify(conn, &sc_svc.attrs[1], sc_value, sizeof(sc_value));
        if (err) {
            printk("Service Changed notification failed (err %d)\n", err);
        } else {
            printk("Service Changed notification sent\n");
        }
    }

  •  I have tried to expose the sc_indicate(0x00010xffff); and use it on the connected callback so that the services get refreshed but dont see anything changing on nRF Connect application on iOS with these changes.

    static void connected(struct bt_conn *conn, uint8_t err) {
      char addr[BT_ADDR_LE_STR_LEN];
      const bt_addr_le_t *addr_info = bt_conn_get_dst(conn);
      sc_indicate(0x0001, 0xffff);
      start_notif_timer();                                        //Starting timer to notfy for battery data after 5 seconds
      atomic_set(&is_advertising,0);
      atomic_set(&is_connected,1);
      wdt_wdtFeed();
      k_timer_stop(&fast_adv_timer);
      k_timer_start(&wdttimer_feed, K_SECONDS(AVDERTISING_UPDATE_SEC), K_SECONDS(AVDERTISING_UPDATE_SEC));
      k_timer_stop(&advertising_timer);
      //Checking connection count and referencing local variable around that
      if(!local_connection){
        local_connection = bt_conn_ref(conn);
      }
      if (is_first_conn)    hrm_sensor_indication_off();        //Coming out of first time connection indication
      static struct bt_gatt_exchange_params exchange_params;
    	exchange_params.func = exchange_func;
    	int res = bt_gatt_exchange_mtu(conn, &exchange_params);
    	if (err) {
    		printk("Connection failed (err 0x%02x)\n", err);
    	} else {
    		printk("Connected\n");
    	}
      // if (bt_conn_set_security(conn, BT_SECURITY_L1)) {
    	// 	printk("Failed to set security : %d\n", bonded_device_count); 
    	// }
      // bt_set_bondable(true);
    }

  •  
    I just tried the above flow with an android phone, and the flow works on it. After manually calling "Refresh Services" got the correct order of the services and characteristics.
    In this one I saw GATT ATTRIBUTE (0x1801) which contains the services changed characteristics to be present twice. 

    And on iOS I am still stuck on the same page where the services are still cached and seeing on nRF Connect application, my custom application is stuck in connection as its trying to read some info from the fixed UUIDs and it reads those values to be garbage.

Related