This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf52832 bonding to apple iphone

Hi Friend,

I use nrf252832 MCU and SDK 15.3, 

I would like to Implement below function, 

1:Device bond phone A without password first , the phone A popups a bonding dialog box;

2: Disconnect phone A and  bond phone B,  the phone B popups a bonding dialog box;

Now it is right;

3:Then I connect phone A back, I want phone A to popup a bonding dialog box again;

If phone A is android phone ,it is ok, but if the phone A is a apple iPhone, it does not popup a bonding dialog box again and pair fail.

How can I bond the iPhone A back? 

The MAC address adding 1 seems make it work,but it is not a good methed.

Thanks!

  • #define SEC_PARAM_TIMEOUT               30                                           /**< Timeout for Pairing Request or Security Request (in seconds). */
    #define SEC_PARAM_BOND                  1                                            /**< Perform bonding. */
    #define SEC_PARAM_MITM                  0                                            /**< Man In The Middle protection not required. */
    #define SEC_PARAM_LESC                  0                                          /**< LE Secure Connections enabled. */
    #define SEC_PARAM_KEYPRESS              0                                           /**< Keypress notifications not enabled. */
    #define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_NONE                         /**< No I/O capabilities. */
    #define SEC_PARAM_OOB                   0                                            /**< Out Of Band data not available. */
    #define SEC_PARAM_MIN_KEY_SIZE          7                                            /**< Minimum encryption key size. */
    #define SEC_PARAM_MAX_KEY_SIZE          16                                           /**< Maximum encryption key size. */
    
    
    /**@brief Function for the Peer Manager initialization.
     *
     * @param[in] erase_bonds  Indicates whether bonding information should be cleared from
     *                         persistent storage during initialization of the Peer Manager.
     */
    static void peer_manager_init(bool erase_bonds)
    {
        
        ret_code_t           err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
        
        if (erase_bonds)
        {
            err_code = pm_peers_delete();
            APP_ERROR_CHECK(err_code);
        }
    
        memset(&m_sec_params, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
        m_sec_params.bond           = SEC_PARAM_BOND;
                    m_sec_params.mitm           = SEC_PARAM_MITM;
        m_sec_params.lesc           = SEC_PARAM_LESC;
        m_sec_params.keypress       = SEC_PARAM_KEYPRESS;
        m_sec_params.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        m_sec_params.oob            = SEC_PARAM_OOB;
        m_sec_params.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        m_sec_params.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        m_sec_params.kdist_own.enc  = 1;
        m_sec_params.kdist_own.id   = 1;
        m_sec_params.kdist_peer.enc = 1;
        m_sec_params.kdist_peer.id  = 1;
                    
    
        err_code = pm_sec_params_set(&m_sec_params);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    //------------------------------------------------------------------
    //------------------------------------------------------------------
    static void pm_evt_handler(pm_evt_t const * p_evt)
    {
       ret_code_t err_code;
    
        pm_handler_on_pm_evt(p_evt);
        pm_handler_disconnect_on_sec_failure(p_evt);
        pm_handler_flash_clean(p_evt);
        
              NRF_LOG_INFO("pm_evt_handler = %d",p_evt->evt_id);
        switch(p_evt->evt_id)
        {
            case PM_EVT_BONDED_PEER_CONNECTED:
                // Update the rank of the peer.
                err_code = pm_peer_rank_highest(p_evt->peer_id);
                break;
            case PM_EVT_CONN_SEC_START:
                break;
            case PM_EVT_CONN_SEC_SUCCEEDED:
                // Update the rank of the peer.
                err_code = pm_peer_rank_highest(p_evt->peer_id);
                            
                break;
            case PM_EVT_CONN_SEC_FAILED:
                // In some cases, when securing fails, it can be restarted directly. Sometimes it can be
                // restarted, but only after changing some Security Parameters. Sometimes, it cannot be
                // restarted until the link is disconnected and reconnected. Sometimes it is impossible
                // to secure the link, or the peer device does not support it. How to handle this error
                // is highly application-dependent.
                                       
                break;
                                             
            case PM_EVT_CONN_SEC_CONFIG_REQ:
            {
                // A connected peer (central) is trying to pair, but the Peer Manager already has a bond
                // for that peer. Setting allow_repairing to false rejects the pairing request.
                // If this event is ignored (pm_conn_sec_config_reply is not called in the event
                // handler), the Peer Manager assumes allow_repairing to be false.
                                             
                                              
                pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
                pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
            }
            break;
            case PM_EVT_CONN_SEC_PARAMS_REQ:
            {
                // If you want to set different security parameters for particular peers, you can do
                // so here. Pass the desired security parameters to pm_conn_sec_params_reply().
                                            
                                              
                                            
                err_code = pm_conn_sec_params_reply(p_evt->conn_handle,
                                                   &m_sec_params,
                                                    p_evt->params.conn_sec_params_req.p_context);
                APP_ERROR_CHECK(err_code);
            } break;
            case PM_EVT_STORAGE_FULL:
                // Run garbage collection on the flash.
                err_code = fds_gc();
                if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
                {
                    // Retry.
                }
                else
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
            case PM_EVT_ERROR_UNEXPECTED:
                // Assert.
                APP_ERROR_CHECK(p_evt->params.error_unexpected.error);
                break;
            case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
                break;
            case PM_EVT_PEER_DATA_UPDATE_FAILED:
                // Assert.
                APP_ERROR_CHECK_BOOL(false);
                break;
            case PM_EVT_PEER_DELETE_SUCCEEDED:
                break;
            case PM_EVT_PEER_DELETE_FAILED:
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error);
                break;
            case PM_EVT_PEERS_DELETE_SUCCEEDED:
                // At this point it is safe to start advertising or scanning.
                break;
            case PM_EVT_PEERS_DELETE_FAILED:
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peers_delete_failed_evt.error);
                break;
            case PM_EVT_LOCAL_DB_CACHE_APPLIED:
                break;
            case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
                // The local database has likely changed, send service changed indications.
                pm_local_database_has_changed();
                break;
            case PM_EVT_SERVICE_CHANGED_IND_SENT:
                break;
            case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
                break;
                                    default:
                                            break;
        }
    }
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                                                    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN,m_conn_handle,BLE_TX_CONNECT_POWER);
                                                    APP_ERROR_CHECK(err_code);
                                    
                                    NRF_LOG_INFO("MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x",p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[0],\
                                      p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[1],\
                                    p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[2],\
                                    p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[3],\
                                    p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[4],\
                                    p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[5]);
                                        
                            
                                                    pm_conn_secure(m_conn_handle,false);
                break;

  • After connection, the device calls the function pm_conn_secure(m_conn_handle,false)to trigger the bonding, is that correct?

  • Hi,

    Rickon said:
    After connection, the device calls the function pm_conn_secure(m_conn_handle,false)to trigger the bonding, is that correct?

    Yes, that is correct.

    The Peer manager does not allow re-pairing by default. It will reject a pairing request from an already bonded peer. 

    You can allow re-pairing by setting allow_repairing to true, you can find it under PM_EVT_CONN_SEC_CONFIG_REQ event.

    EDIT:

    allow_repairing set to true will not work in this case. It will allow rebonding in the case where phone have erased bonding information while the nRF device still have it.

    Sorry for the confusion.

  • I have set it to true, but it return error :4102, please see below info

      case PM_EVT_CONN_SEC_CONFIG_REQ:
    
            {
    
                // Reject pairing request from an already bonded peer.
    
                pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true};
    
                pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
    
            } break;
            
            
            0> <info> app: MAC ADDRESS = B2:FD:19:A0:04:79
     0> <info> app: pm_evt_handler = 5
     0> <info> app: pm_evt_handler = 1
     0> <info> peer_manager_handler: Connection security failed: role: Peripheral, conn_handle: 0x0, procedure: Encryption, error: 4102
     0> <warning> peer_manager_handler: Disconnecting conn_handle 0.
     0> <info> app: pm_evt_handler = 3

  • Hi, 

    The error message indicate (4102 = 0x1006 = PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING). This issue should be fixed by simply removing the bond on the phone as well. I guess you have to manually delete the bonding information on your phone by going into Settings -> Bluetooh -> your device -> "Forget your device".

Related