nRF52832 pm_conn_secure() return 0x3002

I have implemented bonding mechanism in nRF52832 firmware. But when I request nRF Connect to connect nRF52832 second time. nRF52832 pm_conn_secure() return 0x3002 and nRF Connect log message shows "authentication failed with status BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP".

nRF52832 log messages:

 0> <info> app: Version 1.0.0
 0>
 0> <info> app: ========| flash info |========
 0> <info> app: erase unit:   4096 bytes
 0> <info> app: program unit: 4 bytes
 0> <info> app: end address: 0x7FFFF
 0> <info> app: ==============================
 0> <info> app_timer: RTC: initialized.
 0> <debug> app: NOR_DATA_PERIOD=819
 0>
 0> <debug> app: NOR_RECORD_PERIOD=8192
 0>
 0> <info> app: bsp_button_longkey_handler 0.
 0> <warning> app: Battery volage 102mV is too low
 0>
 0> <warning> app: Battery volage 8mV is too low
 0>
 0> <info> app: Reg 9 A
 0> <info> app: bsp_button_longkey_handler 1.
 0> <debug> nrf_ble_gatt: Requesting to update ATT MTU to 185 bytes on connection 0x0.
 0> <info> app: BLE_GAP_EVT_CONNECTED
 0>
 0> <debug> app: state=1
 0>
 0> <debug> nrf_ble_gatt: ATT MTU updated to 185 bytes on connection 0x0 (response).
 0> <info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST
 0>
 0> <info> app: PM_EVT_CONN_SEC_SUCCEEDED
 0>
 0> <info> app: Connection secured: role: 1, conn_handle: 0x0, procedure: 2.
 0> <info> app: BLE_GAP_EVT_AUTH_STATUS
 0>
 0> <info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST
 0>
 0> <info> app: PM_EVT_CONN_SEC_SUCCEEDED
 0>
 0> <info> app: Connection secured: role: 1, conn_handle: 0x0, procedure: 1.
 0> <info> app: BLE_GAP_EVT_AUTH_STATUS
 0>
 0> <info> app: BLE_GAP_EVT_DISCONNECTED
 0>
 0> <debug> app: state=0
 0>
 0> <debug> nrf_ble_gatt: Requesting to update ATT MTU to 185 bytes on connection 0x0.
 0> <info> app: PM_EVT_BONDED_PEER_CONNECTED
 0>
 0> <info> app: BLE_GAP_EVT_CONNECTED
 0>
 0> <debug> app: state=1
 0>
 0> <debug> nrf_ble_gatt: ATT MTU updated to 185 bytes on connection 0x0 (response).
 0> <info> app: PM_EVT_CONN_SEC_CONFIG_REQ
 0>
 0> <info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST
 0>
 0> <info> app: PM_EVT_CONN_SEC_FAILED
 0>
 0> <info> app: Faield to secure connection with handle 00.
 0> <info> app: BLE_GAP_EVT_AUTH_STATUS
 0>
 0> <warning> app: sd_ble_gap_disconnect() failed, errCode=0x8
 0>
 0> <info> app: BLE_GAP_EVT_DISCONNECTED
 0>
 0> <debug> app: state=0
 0>
 0> <debug> app: _securityRequestHandler
 0>
 0> <warning> peer_manager: pm_conn_secure() e
 0>
 0> <warning> peer_manager: pm_conn_secure() return 0x3002
 0>
 0> <warning> app: pm_conn_secure() failed
 0>

nRF Connect log messages:

13:27:42.245    Using nrf-device-lib-js version: 0.4.11
13:27:42.245    Using nrf-device-lib version: 0.11.8
13:27:42.245    Using nrfjprog DLL version: 10.15.4
13:27:42.245    Using JLink version: JLink_V7.66a
13:27:42.245    Installed JLink version does not match the provided version (V7.58b)
13:27:42.471    Updated list of uuids with data from github.com/.../v1
13:27:58.686    Selected device with s/n F092AF29DAF8
13:27:58.692    Device setup completed
13:27:58.692    Connectivity firmware version: ble-connectivity 4.1.4+Mar-11-2021-08-36-04. SoftDevice API version: 5. Baud rate: 1000000.
13:27:58.693    Opening adapter connected to COM5
13:27:59.638    Successfully opened COM5. Baud rate: 1000000. Flow control: none. Parity: none.
13:27:59.639    Reset performed on adapter COM5
13:28:00.703    Adapter connected to COM5 opened
13:28:05.416    Scan started
13:28:33.884    Connecting to device
13:28:36.201    Connected to device E8:20:9F:75:90:08: interval: 7.5ms, timeout: 4000ms, latency: 0
13:28:36.218    ATT MTU updated for device E8:20:9F:75:90:08, new value is 185
13:28:36.488    Attribute value read, handle: 0x03, value (0x): 41-4E-43-53-32
13:28:41.264    Connection parameters updated for device E8:20:9F:75:90:08: interval 15ms, timeout 3000ms, latency: 0
13:28:45.213    Security updated, mode:1, level:3
13:29:20.448    Security updated, mode:1, level:3
13:29:20.500    Storing bond info for device E8:20:9F:75:90:08
13:29:28.505    Device closed.
13:29:39.205    Selected device with s/n F092AF29DAF8
13:29:39.209    Device setup completed
13:29:39.209    Connectivity firmware version: ble-connectivity 4.1.4+Mar-11-2021-08-36-04. SoftDevice API version: 5. Baud rate: 1000000.
13:29:39.210    Opening adapter connected to COM5
13:29:40.137    Successfully opened COM5. Baud rate: 1000000. Flow control: none. Parity: none.
13:29:40.138    Reset performed on adapter COM5
13:29:41.215    Adapter connected to COM5 opened
13:29:43.952    Scan started
13:29:52.041    Connecting to device
13:29:55.253    Connected to device E8:20:9F:75:90:08: interval: 7.5ms, timeout: 4000ms, latency: 0
13:29:55.266    ATT MTU updated for device E8:20:9F:75:90:08, new value is 185
13:29:55.279    Authentication failed with status BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP
13:29:55.302    Disconnected from device E8:20:9F:75:90:08, reason: BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION

  • #include "sdk_config.h"
    #include "advertising.h"
    #include "ble_conn_state.h"
    #include "error.h"
    #include "fds.h"
    #include "nrf_log.h"
    #include "peer_manager.h"
    #include "peer_manager_handler.h"
    #include "peer_manager_types.h"
    #include "security.h"
    #include "timer.h"
    
    static void _pmEvtHandler(pm_evt_t const * pEvt) {
        ret_code_t errCode;
    
        switch (pEvt->evt_id) {
            case PM_EVT_BONDED_PEER_CONNECTED:
            {
                NRF_LOG_INFO("PM_EVT_BONDED_PEER_CONNECTED\n");
                timerSecRequestStart();
            }
            break;
    
            case PM_EVT_CONN_SEC_SUCCEEDED:
            {
                NRF_LOG_INFO("PM_EVT_CONN_SEC_SUCCEEDED\n");
                pm_conn_sec_status_t status;
                errCode = pm_conn_sec_status_get(pEvt->conn_handle, &status);
                if (errCode != NRF_SUCCESS) {
                    NRF_LOG_WARNING("pm_conn_sec_status_get() failed, errCode=0x%x\n", errCode);
                    return;
                }
    
                if (status.mitm_protected) {
                    NRF_LOG_INFO("Connection secured: role: %d, conn_handle: 0x%x, procedure: %d.",
                                 ble_conn_state_role(pEvt->conn_handle),
                                 pEvt->conn_handle,
                                 pEvt->params.conn_sec_succeeded.procedure);
                } else {
                    NRF_LOG_INFO("Connection isn't secured: disconnecting\n");
                    pm_peer_id_t peerId;
                    errCode = pm_peer_id_get(pEvt->conn_handle, &peerId);
                    if (errCode != NRF_SUCCESS) {
                        NRF_LOG_WARNING("pm_peer_id_get() failed, errCode=0x%x\n", errCode);
                        return;
                    }
    
                    errCode = sd_ble_gap_disconnect(pEvt->conn_handle,
                                                   BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                    if ((errCode != NRF_SUCCESS) && (errCode != NRF_ERROR_INVALID_STATE)) {
                        NRF_LOG_INFO("sd_ble_gap_disconnect() failed, errCode=0x%x\n", errCode);
                        return;
                    }
                }
                
                
            }
            break;
    
            case PM_EVT_CONN_SEC_FAILED:
            {
                NRF_LOG_INFO("PM_EVT_CONN_SEC_FAILED");
                NRF_LOG_INFO("Faield to secure connection with handle 0%x.", pEvt->conn_handle);
                errCode = sd_ble_gap_disconnect(pEvt->conn_handle,
                                          BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if ((errCode != NRF_SUCCESS) && (errCode != NRF_ERROR_INVALID_STATE)) {
                    NRF_LOG_INFO("sd_ble_gap_disconnect() failed, errCode=0x%x\n", errCode);
                    return;
                }
                //pEvt->conn_handle = BLE_CONN_HANDLE_INVALID;
                /* Often, when securing fails, it shouldn't be restarted, for security reasons.
                 * Other times, 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:
            {
                NRF_LOG_INFO("PM_EVT_CONN_SEC_CONFIG_REQ\n");
                // Reject pairing request from an already bonded peer.
                pm_conn_sec_config_t config = {.allow_repairing = false};
                pm_conn_sec_config_reply(pEvt->conn_handle, &config);
            }
            break;
    
            case PM_EVT_STORAGE_FULL:
            {
                NRF_LOG_INFO("PM_EVT_STORAGE_FULL\n");
                // Run garbage collection on the flash.
                errCode = fds_gc();
                if (errCode == FDS_ERR_NO_SPACE_IN_QUEUES)
                {
                    // Retry.
                }
                else
                {
                    APP_ERROR_CHECK(errCode);
                }
            }
            break;
    
            case PM_EVT_PEERS_DELETE_SUCCEEDED:
            {
                NRF_LOG_DEBUG("PM_EVT_PEERS_DELETE_SUCCEEDED\n");
                advertisingStart();
            }
            break;
    
            case PM_EVT_PEER_DATA_UPDATE_FAILED:
            {
                NRF_LOG_DEBUG("PM_EVT_PEER_DATA_UPDATE_FAILED\n");
                // Assert.
                APP_ERROR_CHECK(pEvt->params.peer_data_update_failed.error);
            }
            break;
    
            case PM_EVT_PEER_DELETE_FAILED:
            {
                NRF_LOG_DEBUG("PM_EVT_PEER_DELETE_FAILED\n");
                // Assert.
                APP_ERROR_CHECK(pEvt->params.peer_delete_failed.error);
            }
            break;
    
            case PM_EVT_PEERS_DELETE_FAILED:
            {
                NRF_LOG_DEBUG("PM_EVT_PEERS_DELETE_FAILED\n");
                // Assert.
                APP_ERROR_CHECK(pEvt->params.peers_delete_failed_evt.error);
            }
            break;
    
            case PM_EVT_ERROR_UNEXPECTED:
            {
                NRF_LOG_DEBUG("PM_EVT_ERROR_UNEXPECTED\n");
                // Assert.
                APP_ERROR_CHECK(pEvt->params.error_unexpected.error);
            } break;
    
            case PM_EVT_CONN_SEC_START:
            case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
            case PM_EVT_PEER_DELETE_SUCCEEDED:
            case PM_EVT_LOCAL_DB_CACHE_APPLIED:
            case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
                // This can happen when the local DB has changed.
            case PM_EVT_SERVICE_CHANGED_IND_SENT:
            case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
            default:
                break;
        }
    }
    
    
    /**@brief Function for the Peer Manager initialization.
     */
    int peerManagerInit(void) {
        ble_gap_sec_params_t secParam;
        ret_code_t errCode;
        
        errCode = pm_init();
        if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("pm_init() failed, errCode=0x%x\n", errCode);
            return ERROR_PEER_MANAGER_INITIALIZE_FAIL;
        }
    
        securityParametersGet(&secParam);   
        errCode = pm_sec_params_set(&secParam);
        if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("pm_sec_params_set() failed, errCode=0x%x\n", errCode);
            return ERROR_PEER_MANAGER_INITIALIZE_FAIL;
        } 
        
        errCode = pm_register(_pmEvtHandler);
        if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("pm_register() failed, errCode=0x%x\n", errCode);
            return ERROR_PEER_MANAGER_INITIALIZE_FAIL;
        } 
    
        return 0;
    }
    
    void securityParametersGet(ble_gap_sec_params_t* pSecParam) {
        memset(pSecParam, 0, sizeof(ble_gap_sec_params_t));
        
        // Security parameters to be used for all security procedures.
        pSecParam->bond           = SEC_PARAM_BOND;
        pSecParam->mitm           = SEC_PARAM_MITM;
        pSecParam->lesc           = SEC_PARAM_LESC;
        pSecParam->keypress       = SEC_PARAM_KEYPRESS;
        pSecParam->io_caps        = SEC_PARAM_IO_CAPABILITIES;
        pSecParam->oob            = SEC_PARAM_OOB;
        pSecParam->min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        pSecParam->max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        pSecParam->kdist_own.enc  = 1;
        pSecParam->kdist_own.id   = 1;
        pSecParam->kdist_peer.enc = 1;
        pSecParam->kdist_peer.id  = 1;
        
    }    
        
        
    
    8865.gap.h
    #include "sdk_config.h"
    #include "ble.h"
    #include "ble_conn_params.h"
    #include "ble_gap.h"
    #include "gap.h"
    #include "error.h"
    #include "nrf_log.h"
    
    #define DEVICE_NAME       "ANCS2"                         /**< Name of the device. Will be included in the advertising data. */
    #define STATIC_PASSKEY    "123456"                        /**< Static passkey. */
    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.5 seconds). */
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(30, UNIT_1_25_MS) /**< Maximum acceptable connection interval (1 second). */
    #define SLAVE_LATENCY     0                               /**< Slave latency. */
    #define CONN_SUP_TIMEOUT  MSEC_TO_UNITS(3000, UNIT_10_MS) /**< Connection supervisory time-out (4 seconds). */
    
    static ble_opt_t _gStaticPasskeyOption;	/**< Pointer to the struct containing static pin option. */
    
    /**@brief Function for initializing GAP connection parameters.
     *
     * @details Use this function to set up all necessary GAP (Generic Access Profile)
     *          parameters of the device. It also sets the permissions and appearance.
     */
    int gapParamsInit(void) {
        ret_code_t              errCode;
        ble_gap_conn_params_t   gapConnParams;
        ble_gap_conn_sec_mode_t secMode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&secMode);
    
        errCode = sd_ble_gap_device_name_set(&secMode, (const uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME));
        if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("sd_ble_gap_device_name_set() failed, errCode=0x%x", errCode);
            return ERROR_GAP_INITIALIZE_FAIL;
        }
    
        memset(&gapConnParams, 0, sizeof(gapConnParams));
    
        gapConnParams.min_conn_interval = MIN_CONN_INTERVAL;
        gapConnParams.max_conn_interval = MAX_CONN_INTERVAL;
        gapConnParams.slave_latency     = SLAVE_LATENCY;
        gapConnParams.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        errCode = sd_ble_gap_ppcp_set(&gapConnParams);
        if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("sd_ble_gap_ppcp_set() failed, errCode=0x%x", errCode);
            return ERROR_GAP_INITIALIZE_FAIL;
        }
    
    #if PASSKEY_ENABLED
        uint8_t passkey[] = STATIC_PASSKEY;
    	_gStaticPasskeyOption.gap_opt.passkey.p_passkey = passkey;
    	errCode = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &_gStaticPasskeyOption);
    	if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("sd_ble_opt_set() failed, errCode=0x%x", errCode);
            return ERROR_GAP_INITIALIZE_FAIL;
        }
    #endif
        return 0;
    }
    
    
    
    5226.security.h

  • int main(void) {


        timerInit();
        peerManagerInit();
        gapParamsInit();
        services_init();
        advertisingInit();
        conn_params_init();
        ...
    }

    #define SECURITY_REQUEST_PERIOD         APP_TIMER_TICKS(2500)

    int timerInit(void) {
        ret_code_t errCode = app_timer_create(&_gSecRequestTimerID, APP_TIMER_MODE_SINGLE_SHOT, _securityRequestHandler);
        if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("app_timer_create(_gSecRequestTimerID) failed\n");
            return ERROR_TIMER_CREATE_FAIL;
        }

        _gTimerSecRequestRunning      = false;

        ...

        return 0;
    }

    int timerSecRequestStart(void) {
        if (!_gTimerSecRequestRunning) {
            const ret_code_t errCode = app_timer_start(_gSecRequestTimerID, SECURITY_REQUEST_PERIOD, NULL);
            if (errCode != NRF_SUCCESS) {
                NRF_LOG_WARNING("app_timer_start(_gSecRequestTimerID) failed\n");
                return ERROR_TIMER_START_FAIL;
            }    
        }

        _gTimerSecRequestRunning = true;

        return 0;
    }

    static void ble_evt_handler(ble_evt_t const* pBleEvt, void* pContext)
    {
        ret_code_t errCode = NRF_SUCCESS;
        
        switch (pBleEvt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
            {
                NRF_LOG_INFO("BLE_GAP_EVT_CONNECTED\n");
                BLE_UART_SetState(BLE_NUS_STATE_CONNECT);
                errCode = bsp_indication_set(BSP_INDICATE_CONNECTED);
                if (errCode != NRF_SUCCESS) {
                    NRF_LOG_WARNING("bsp_indication_set() failed, errCode=0x%x\n", errCode);
                    return;
                }    

                m_cur_conn_handle = pBleEvt->evt.gap_evt.conn_handle;

                errCode = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_cur_conn_handle);
                if (errCode != NRF_SUCCESS) {
                    NRF_LOG_WARNING("nrf_ble_qwr_conn_handle_assign() failed, errCode=0x%x\n", errCode);
                    return;
                }

    #if PASSKEY_ENABLED
                ble_gap_sec_params_t secParam;
                securityParametersGet(&secParam);
                //secParam.bond           = SEC_PARAM_BOND;
                //secParam.mitm           = SEC_PARAM_MITM;
                errCode = sd_ble_gap_authenticate(m_cur_conn_handle, &secParam);
                if (errCode != NRF_SUCCESS) {
                    NRF_LOG_WARNING("sd_ble_gap_authenticate() failed, errCode=0x%x\n", errCode);
                    return;
                }
    #endif           
            }    
            break;

            case BLE_GAP_EVT_DISCONNECTED:
            {
                NRF_LOG_INFO("BLE_GAP_EVT_DISCONNECTED\n");
                if (fstorageGetState() == FSTORAGE_STATE_ERASED) {
                    fstorageWaitUpdateRecordFinish();
                }
                BLE_UART_SetState(BLE_NUS_STATE_DISCONNECT);
                m_cur_conn_handle = BLE_CONN_HANDLE_INVALID;
            }    
            break;

            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
            {
                NRF_LOG_INFO("BLE_GAP_EVT_SEC_PARAMS_REQUEST\n");
    #if 0

                ble_gap_sec_params_t secParam;
                securityParametersGet(&secParam);
                errCode = sd_ble_gap_sec_params_reply(m_cur_conn_handle,
                                                      BLE_GAP_SEC_STATUS_SUCCESS,
                                                      &secParam,
                                                      NULL);
                if ((errCode != NRF_SUCCESS) && (errCode != NRF_ERROR_INVALID_STATE)) {
                    NRF_LOG_WARNING("sd_ble_gap_sec_params_reply() failed, errCode=0x%x\n", errCode);
                    return;
                }

    #endif
            }
            break;

            case BLE_GAP_EVT_AUTH_STATUS:
            {
                NRF_LOG_INFO("BLE_GAP_EVT_AUTH_STATUS\n");
    #if PASSKEY_ENABLED
                if (pBleEvt->evt.gap_evt.params.auth_status.auth_status != BLE_GAP_SEC_STATUS_SUCCESS) {
                    errCode = sd_ble_gap_disconnect(m_cur_conn_handle,
                                                    BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                    if (errCode != NRF_SUCCESS) {
                        NRF_LOG_WARNING("sd_ble_gap_disconnect() failed, errCode=0x%x\n", errCode);
                        return;
                    }
                }
    #endif
            }
            break;






            default:
                // No implementation needed.
            break;
        }
    }

  • I found sec_status is set to BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP in smd_params_reply(). So nRF Connect shows "Authentication failed with status BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP".

    log messages.

    # SEGGER J-Link RTT Viewer V6.32i Terminal Log File
    # Compiled: 15:22:50 on Jul 24 2018
    # Logging started @ 25 Jul 2022 17:00:50
     0> <info> app: Version 1.0.0
     0>
     0> <info> app: ========| flash info |========
     0> <info> app: erase unit:   4096 bytes
     0> <info> app: program unit: 4 bytes
     0> <info> app: end address: 0x7FFFF
     0> <info> app: ==============================
     0> <info> app_timer: RTC: initialized.
     0> <debug> app: NOR_DATA_PERIOD=819
     0>
     0> <debug> app: NOR_RECORD_PERIOD=8192
     0>
     0> <info> app: bsp_button_longkey_handler 0.
     0> <warning> app: Battery volage 222mV is too low
     0>
     0> <warning> app: Battery volage 42mV is too low
     0>
     0> <warning> app: Battery volage 0mV is too low
     0>
     0> <info> app: POWER_ON.
     0> <info> app: External devices initializing start
     0> <info> app: External devices initializing finish
     0> <info> app: bsp_button_longkey_handler 1.
     0> <debug> nrf_ble_gatt: Requesting to update ATT MTU to 185 bytes on connection 0x0.
     0> <info> app: PM_EVT_BONDED_PEER_CONNECTED
     0>
     0> <info> app: BLE_GAP_EVT_CONNECTED
     0>
     0> <debug> app: state=1
     0>
     0> <debug> nrf_ble_gatt: ATT MTU updated to 185 bytes on connection 0x0 (response).
     0> <debug> peer_manager_smd: smd_params_reply() e
     0>
     0> <info> app: PM_EVT_CONN_SEC_CONFIG_REQ
     0>
     0> <debug> peer_manager_smd: smd_params_reply() BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP 2
     0>
     0> <debug> peer_manager_smd: smd_params_reply() return 0x0
     0>
     0> <info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST
     0>
     0> <info> app: PM_EVT_CONN_SEC_FAILED
     0> <info> app: Faield to secure connection with handle 00
     0>
     0> <info> app: BLE_GAP_EVT_AUTH_STATUS
     0>
     0> <warning> app: sd_ble_gap_disconnect() failed, errCode=0x3002
     0>
     0> <info> app: BLE_GAP_EVT_DISCONNECTED
     0>
     0> <debug> app: state=0
     0>
     0> <debug> app: _securityRequestHandler
     0>

    ret_code_t smd_params_reply(uint16_t                 conn_handle,
                                ble_gap_sec_params_t   * p_sec_params,
                                ble_gap_lesc_p256_pk_t * p_public_key)
    {
        NRF_LOG_DEBUG("smd_params_reply() e\n");
        NRF_PM_DEBUG_CHECK(m_module_initialized);

        uint8_t              role       = ble_conn_state_role(conn_handle);
        ret_code_t           err_code   = NRF_SUCCESS;
        uint8_t              sec_status = BLE_GAP_SEC_STATUS_SUCCESS;
        ble_gap_sec_keyset_t sec_keyset;

        memset(&sec_keyset, 0, sizeof(ble_gap_sec_keyset_t));
        if (role == BLE_GAP_ROLE_PERIPH)
        {
            // Set the default value for allowing repairing at the start of the sec proc. (for peripheral)
            ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, false);
        }

        if (role == BLE_GAP_ROLE_INVALID)
        {
            return BLE_ERROR_INVALID_CONN_HANDLE;
        }

    #if PM_RA_PROTECTION_ENABLED
        if (ast_peer_blacklisted(conn_handle)) //Check for repeated attempts here.
        {
            sec_status = BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS;
        }
        else
    #endif // PM_RA_PROTECTION_ENABLED
        if (p_sec_params == NULL)
        {
            // NULL params means reject pairing.
            sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP;
            NRF_LOG_DEBUG("smd_params_reply() BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP 1\n");
        }
        else
        {
            if ((im_peer_id_get_by_conn_handle(conn_handle) != PM_PEER_ID_INVALID) &&
                (role == BLE_GAP_ROLE_PERIPH) &&
                !allow_repairing(conn_handle))
            {
                // Bond already exists. Reject the pairing request if the user doesn't intervene.
                send_config_req(conn_handle);
                if (!allow_repairing(conn_handle))
                {
                    // Reject pairing.
                    sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP;
                    NRF_LOG_DEBUG("smd_params_reply() BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP 2\n");
                }
            }

            if (!p_sec_params->bond)
            {
                // Pairing, no bonding.
                sec_keyset.keys_own.p_pk  = p_public_key;
                sec_keyset.keys_peer.p_pk = &m_peer_pk;
            }
            else if (sec_status != BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP)
            {
                // Bonding is to be performed, prepare to receive bonding data.
                err_code = sec_keyset_fill(conn_handle, role, p_public_key, &sec_keyset);
            }
        }

        if (err_code == NRF_SUCCESS)
        {
            // Everything OK, reply to SoftDevice. If an error happened, the user is given an
            // opportunity to change the parameters and retry the call.
            if (role == BLE_GAP_ROLE_PERIPH)
            {
                err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, p_sec_params, &sec_keyset);
            }
            else
            {
                err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, NULL, &sec_keyset);
            }
        }

        NRF_LOG_DEBUG("smd_params_reply() return 0x%x\n", err_code);
        return err_code;
    }

  • Hi, 

    Error 0x3002 means BLE_ERROR_INVALID_CONN_HANDLE . 
    Please check how pm_conn_secure() is called. 

    I've noticed that you have opened quite a few support cases regarding the same issue on pairing. Please try to focus on one ticket. 

    I would suggest to study the example and make as few modification as possible. 

    Which device you used on the central side ? 
    Please try to capture a sniffer trace. 

Related