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

Swift Pairing for custom gatt service

Hi,

I am using custom gatt service & I have included some of the code which supports swift pairing from ble_hid_mouse example. Here is my sniffer log -

mtu_log.pcapng

& the jlink rtt log -

paired - Copy.txt

For my application, the MTU size is 32 & data length is 36.

Windows keeps negotiating the size to be 512.

After I pair to the peripheral by connecting through the Windows bluetooth menu, it takes 1 minute to establish the ble connection & start data communication. If I dont pair, then the connection is quick. Now I know you will tell me the app has to make a connection. But I would also like to support manual pairing. Our device gets bricked if someone accidentally pairs with the device through Windows bluetooth menu. To avoid this I had to add the swift pairing support.

How do I expedite the connection on Windows for swift pairing? (note the same firmware without swift pairing feature works on Android OS perfectly fine with or without pairing.)

Parents Reply Children
  • I think the main problem here is that the slave seem to always send a "Security Request: AuthReq: Bonding", which should not be necessary, since the link is already encrypted or in the process of being encrypted. I think that is what is causing the master to misbehave by sending a LL_PING_RSP later.

    If you open any of the other SDK examples as-is that support bonding, you will see that it is not sending a "Security Request: AuthReq: Bonding". So we need to try to find out what is causing this in your application.

    Can you provide the source for peer_manager_init(), sys_evt_dispatch(), ble_evt_dispatch(),  and pm_evt_handler()?

    Is it possible that you are deleting bonds here somewhere?

    *maybe check this first* Is it possible you are calling pm_conn_secure() somewhere?

    Can you provide your defines of FDS*/FSTORAGE* in sdk_config.h?

    What security level have you set for your various characteristics and services? For instance have you set BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM() or other? See ble_gap.h for a list of available BLE_GAP_CONN_SEC_MODE_SET_MACROS.

    Best regards,
    Kenneth

  • Ahh I see, do you need the code snippets for peer_manager_init(), sys_evt_dispatch() and pm_evt_handler() or do you need the location where these are being called?

    static void peer_manager_init()
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t           err_code;
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
        // Security parameters to be used for all security procedures.
        sec_param.bond           = SEC_PARAM_BOND;
        sec_param.mitm           = SEC_PARAM_MITM;
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;
        sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        sec_param.oob            = SEC_PARAM_OOB;
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        sec_param.kdist_own.enc  = 1;
        sec_param.kdist_own.id   = 1;
        sec_param.kdist_peer.enc = 1;
        sec_param.kdist_peer.id  = 1;
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }

    #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 not 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. */

    I couldnt find sys_evt_dispatch() in my project.

    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_flash_clean(p_evt);
    	/*not included*/
    	switch (p_evt->evt_id)
        {
    		case PM_EVT_BONDED_PEER_CONNECTED:
            {
                NRF_LOG_INFO("PM_EVT_BONDED_PEER_CONNECTED - Connected to a previously bonded device.");
            } break;
    		case PM_EVT_CONN_SEC_START:
    			NRF_LOG_INFO("PM_EVT_CONN_SEC_START");
    		break;
    		case PM_EVT_CONN_SEC_SUCCEEDED:
            {
                NRF_LOG_INFO("PM_EVT_CONN_SEC_SUCCEEDED - Connection secured: role: %d, conn_handle: 0x%x, procedure: %d.", ble_conn_state_role(p_evt->conn_handle),
                             p_evt->conn_handle, p_evt->params.conn_sec_succeeded.procedure);
            } break;
    		case PM_EVT_CONN_SEC_FAILED:
            {
    			NRF_LOG_INFO("PM_EVT_CONN_SEC_FAILED");
                /* 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");
                // 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;
    		case PM_EVT_CONN_SEC_PARAMS_REQ:
    			NRF_LOG_INFO("PM_EVT_CONN_SEC_PARAMS_REQ");
    		break;
    		case PM_EVT_STORAGE_FULL:
            {
    			NRF_LOG_INFO("PM_EVT_STORAGE_FULL");
                // Run garbage collection on the flash.
                err_code = fds_gc();
                if (err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
                {
                    // Retry.
                }
                else
                {
                    APP_ERROR_CHECK(err_code);
                }
            } break;
    		case PM_EVT_ERROR_UNEXPECTED:
            {
    			NRF_LOG_INFO("PM_EVT_ERROR_UNEXPECTED");
                // Assert.
                APP_ERROR_CHECK(p_evt->params.error_unexpected.error);
            } break;
    		case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
    			NRF_LOG_INFO("PM_EVT_PEER_DATA_UPDATE_SUCCEEDED");
    			if (p_evt->params.peer_data_update_succeeded.flash_changed && (p_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_BONDING))
                {
                    NRF_LOG_INFO("New Bond, add the peer to the whitelist if possible");
    				// Note: You should check on what kind of white list policy your application should use.
                    whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR);	/*For Quest*/
                }
            break;
    		case PM_EVT_PEER_DATA_UPDATE_FAILED:
            {
    			NRF_LOG_INFO("PM_EVT_PEER_DATA_UPDATE_FAILED");
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peer_data_update_failed.error);
            } break;		
    		case PM_EVT_PEER_DELETE_SUCCEEDED:
    			NRF_LOG_INFO("PM_EVT_PEER_DELETE_SUCCEEDED");
    		break;
            case PM_EVT_PEERS_DELETE_SUCCEEDED:
    			NRF_LOG_INFO("PM_EVT_PEERS_DELETE_SUCCEEDED");
                advertising_start(false);
            break;		
    		case PM_EVT_PEER_DELETE_FAILED:
            {
    			NRF_LOG_INFO("PM_EVT_PEER_DELETE_FAILED");
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error);
            } break;
    		case PM_EVT_PEERS_DELETE_FAILED:
            {
    			NRF_LOG_INFO("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:
    			NRF_LOG_INFO("PM_EVT_LOCAL_DB_CACHE_APPLIED");
    		break;
            case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
    			NRF_LOG_INFO("PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED");
    		break;
                // This can happen when the local DB has changed.
            case PM_EVT_SERVICE_CHANGED_IND_SENT:
    			NRF_LOG_INFO("PM_EVT_SERVICE_CHANGED_IND_SENT");
    		break;
            case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
    			NRF_LOG_INFO("PM_EVT_SERVICE_CHANGED_IND_CONFIRMED");
    		break;
    		case PM_EVT_SLAVE_SECURITY_REQ:
    			NRF_LOG_INFO("PM_EVT_SLAVE_SECURITY_REQ");
    		break;
    		case PM_EVT_FLASH_GARBAGE_COLLECTED:
    			NRF_LOG_INFO("PM_EVT_FLASH_GARBAGE_COLLECTED");
    		break;
    		case PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED:
    			NRF_LOG_INFO("PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED");
    		break;
            default:
                break;
    	}
    }

    FDS defines -

    // <e> FDS_ENABLED - fds - Flash data storage module
    //==========================================================
    #ifndef FDS_ENABLED
    #define FDS_ENABLED 1
    #endif
    // <h> Pages - Virtual page settings
    
    // <i> Configure the number of virtual pages to use and their size.
    //==========================================================
    // <o> FDS_VIRTUAL_PAGES - Number of virtual flash pages to use. 
    // <i> One of the virtual pages is reserved by the system for garbage collection.
    // <i> Therefore, the minimum is two virtual pages: one page to store data and one page to be used by the system for garbage collection.
    // <i> The total amount of flash memory that is used by FDS amounts to @ref FDS_VIRTUAL_PAGES * @ref FDS_VIRTUAL_PAGE_SIZE * 4 bytes.
    
    #ifndef FDS_VIRTUAL_PAGES
    #define FDS_VIRTUAL_PAGES 3
    #endif
    
    // <o> FDS_VIRTUAL_PAGE_SIZE  - The size of a virtual flash page.
     
    
    // <i> Expressed in number of 4-byte words.
    // <i> By default, a virtual page is the same size as a physical page.
    // <i> The size of a virtual page must be a multiple of the size of a physical page.
    // <1024=> 1024 
    // <2048=> 2048 
    
    #ifndef FDS_VIRTUAL_PAGE_SIZE
    #define FDS_VIRTUAL_PAGE_SIZE 1024
    #endif
    
    // <o> FDS_VIRTUAL_PAGES_RESERVED - The number of virtual flash pages that are used by other modules. 
    // <i> FDS module stores its data in the last pages of the flash memory.
    // <i> By setting this value, you can move flash end address used by the FDS.
    // <i> As a result the reserved space can be used by other modules.
    
    #ifndef FDS_VIRTUAL_PAGES_RESERVED
    #define FDS_VIRTUAL_PAGES_RESERVED 0
    #endif
    
    // </h> 
    //==========================================================
    
    // <h> Backend - Backend configuration
    
    // <i> Configure which nrf_fstorage backend is used by FDS to write to flash.
    //==========================================================
    // <o> FDS_BACKEND  - FDS flash backend.
     
    
    // <i> NRF_FSTORAGE_SD uses the nrf_fstorage_sd backend implementation using the SoftDevice API. Use this if you have a SoftDevice present.
    // <i> NRF_FSTORAGE_NVMC uses the nrf_fstorage_nvmc implementation. Use this setting if you don't use the SoftDevice.
    // <1=> NRF_FSTORAGE_NVMC 
    // <2=> NRF_FSTORAGE_SD 
    
    #ifndef FDS_BACKEND
    #define FDS_BACKEND 2
    #endif
    
    // </h> 
    //==========================================================
    
    // <h> Queue - Queue settings
    
    //==========================================================
    // <o> FDS_OP_QUEUE_SIZE - Size of the internal queue. 
    // <i> Increase this value if you frequently get synchronous FDS_ERR_NO_SPACE_IN_QUEUES errors.
    
    #ifndef FDS_OP_QUEUE_SIZE
    #define FDS_OP_QUEUE_SIZE 4
    #endif
    
    // </h> 
    //==========================================================
    
    // <h> CRC - CRC functionality
    
    //==========================================================
    // <e> FDS_CRC_CHECK_ON_READ - Enable CRC checks.
    
    // <i> Save a record's CRC when it is written to flash and check it when the record is opened.
    // <i> Records with an incorrect CRC can still be 'seen' by the user using FDS functions, but they cannot be opened.
    // <i> Additionally, they will not be garbage collected until they are deleted.
    //==========================================================
    #ifndef FDS_CRC_CHECK_ON_READ
    #define FDS_CRC_CHECK_ON_READ 0
    #endif
    // <o> FDS_CRC_CHECK_ON_WRITE  - Perform a CRC check on newly written records.
     
    
    // <i> Perform a CRC check on newly written records.
    // <i> This setting can be used to make sure that the record data was not altered while being written to flash.
    // <1=> Enabled 
    // <0=> Disabled 
    
    #ifndef FDS_CRC_CHECK_ON_WRITE
    #define FDS_CRC_CHECK_ON_WRITE 0
    #endif
    
    // </e>
    
    // </h> 
    //==========================================================
    
    // <h> Users - Number of users
    
    //==========================================================
    // <o> FDS_MAX_USERS - Maximum number of callbacks that can be registered. 
    #ifndef FDS_MAX_USERS
    #define FDS_MAX_USERS 4
    #endif

    FSTORAGE defines -

    // <e> NRF_FSTORAGE_ENABLED - nrf_fstorage - Flash abstraction library
    //==========================================================
    #ifndef NRF_FSTORAGE_ENABLED
    #define NRF_FSTORAGE_ENABLED 1
    #endif
    // <h> nrf_fstorage - Common settings
    
    // <i> Common settings to all fstorage implementations
    //==========================================================
    // <q> NRF_FSTORAGE_PARAM_CHECK_DISABLED  - Disable user input validation
     
    
    // <i> If selected, use ASSERT to validate user input.
    // <i> This effectively removes user input validation in production code.
    // <i> Recommended setting: OFF, only enable this setting if size is a major concern.
    
    #ifndef NRF_FSTORAGE_PARAM_CHECK_DISABLED
    #define NRF_FSTORAGE_PARAM_CHECK_DISABLED 0
    #endif
    
    // </h> 
    //==========================================================
    
    // <h> nrf_fstorage_sd - Implementation using the SoftDevice
    
    // <i> Configuration options for the fstorage implementation using the SoftDevice
    //==========================================================
    // <o> NRF_FSTORAGE_SD_QUEUE_SIZE - Size of the internal queue of operations 
    // <i> Increase this value if API calls frequently return the error @ref NRF_ERROR_NO_MEM.
    
    #ifndef NRF_FSTORAGE_SD_QUEUE_SIZE
    #define NRF_FSTORAGE_SD_QUEUE_SIZE 4
    #endif
    
    // <o> NRF_FSTORAGE_SD_MAX_RETRIES - Maximum number of attempts at executing an operation when the SoftDevice is busy 
    // <i> Increase this value if events frequently return the @ref NRF_ERROR_TIMEOUT error.
    // <i> The SoftDevice might fail to schedule flash access due to high BLE activity.
    
    #ifndef NRF_FSTORAGE_SD_MAX_RETRIES
    #define NRF_FSTORAGE_SD_MAX_RETRIES 8
    #endif
    
    // <o> NRF_FSTORAGE_SD_MAX_WRITE_SIZE - Maximum number of bytes to be written to flash in a single operation 
    // <i> This value must be a multiple of four.
    // <i> Lowering this value can increase the chances of the SoftDevice being able to execute flash operations in between radio activity.
    // <i> This value is bound by the maximum number of bytes that can be written to flash in a single call to @ref sd_flash_write.
    // <i> That is 1024 bytes for nRF51 ICs and 4096 bytes for nRF52 ICs.
    
    #ifndef NRF_FSTORAGE_SD_MAX_WRITE_SIZE
    #define NRF_FSTORAGE_SD_MAX_WRITE_SIZE 4096
    #endif

    pm_conn_secure() is not called in main.c

    I never use the delete_bonds() function & I also dont use BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM().

  • Edit: Removed this reply since it was invalid for new SDK.

  • I tried adding all these functions, seems like they have been deprecated in SDK 16 according to few tickets and the Migration doc.

    I'm getting these errors in my Keil project.

  • Sorry, you are right. I was looking at an old SDK.

    My suggestion now is to take a look at the \examples\ble_peripheral\ble_app_hids_keyboard or ble_hid_mouse, replace all the parameters and callbacks from that project to your project. Double check that you have not by accident modified any of the SDK libraries for instance to test something earlier.

    You will notice that the \examples\ble_peripheral\ble_app_hids_keyboard or ble_hid_mouse will not send the "Security Request: AuthReq: Bonding". If you are not able to find the problem, then only way forward would be to share a project that can be unzipped to the examples\ble_peripheral and run an nRF52-DK to test here.

    Best regards,
    Kenneth

Related