Add Pairing support in existing ble_app_uart_c

Hello All,

SDK version: 15.1.0 (nRF5SDK1510a8c0c4d)

We are having BLE nRf52840 connected with processor over UART. As of now nRf52840 is running modified ble_app_uart_c example and we are able to get the beacon data as well as able to connect to various BLE based sensor to read characteristics data in below fashion:

1> Beacon based data:

     We have modified SDK's API nrf_ble_scan_on_ble_evt() by adding parsing logic of various sensor which send data over beacon and we are then sending it to processor over uart.

2> Connection based data:

     We are using Name/MAC based filter to connect to BLE temperature sensor and get hold on connection handles by parsing its services/characteristics so that we can Read/Write from/to BLE temperature sensor and eventually send data to processor over uart.

our nRf52840 is getting installed with merged .hex file of DFU+SOFT_DEVICE+APP_uart_c in factory and on field we only updates BLE applications with the help of nrfutil. 

Now, We have installed BLE pressure sensor on field which is only allowing characteristic/data read if it is paired (with key:123456) and we got to know that NUS's ble_app_uart_c doesn't support pairing. 

So, I am welcoming all suggestions for:

1> What is the best way to handle this? since we have did changes in files ble_nus_c.c, nrf_ble_scan.c, ble_db_discovery.c in SDK codes along with ble_app_uart_c.c

2> Is there any other example which supports both pairing and UART? 

3> Is there any reference available for merging pairing based example with NUS's app_uart_c? basically we want our BLE to connect with normal sensor as well as pairing based sensors and send received data from  sensor to processor over UART

4> Will the new application with pairing support needs reflash DFU or SOFT_DEVICE? or application/example.hex should be enough?

Thanks in Advance,

Ankit

  • Hi,

    1> What is the best way to handle this? since we have did changes in files ble_nus_c.c, nrf_ble_scan.c, ble_db_discovery.c in SDK codes along with ble_app_uart_c.c

    You are right that the ble_app_uart_c example does not support bonding, but that can be added. Generally, pairing and bonding is handled by the peer manager library, which use FDS for storing the data. So you need to add this libraries to your application.

    Pairing and bonding is mostly the same for peripherals and centrals, but if you want a  central example to refer to, you can take a look at examples/ble_central/ble_app_hrs_c/. This does not include passkey entry, though, which requiers a few more lines. Specifically, after adding support for pairing/bonding, make sure you handle the BLE_GAP_EVT_AUTH_KEY_REQUEST event and reply to it with a call to sd_ble_gap_auth_key_reply().

    2> Is there any other example which supports both pairing and UART? 

    Not officially (unless you mean UART for logging and not NUS in this context). However, the pairing part is independent of most other things, so any example that includes pairing/bonding should work as a reference (regardless of it using NUS or not).

    3> Is there any reference available for merging pairing based example with NUS's app_uart_c? basically we want our BLE to connect with normal sensor as well as pairing based sensors and send received data from  sensor to processor over UART

    There is an old description here, but that is for SDK 12.3.0 and is not entirely up to date with what you need for later SDK versions. But the main things are the same. Generally, take an example as reference and:

    • Copy over any pairing/bonding related code
    • Update your project to include needed libraries and include paths (starting with the peer manager and FDS)
    • Update sdk_config.h to enable relevant features like FDS and the peer manager

    There are quite a few things to remember so I expect things will fail initially, by building and resolving errors one by one you will get it included. This is generally how you add new features and libraries (add what you know you need, then add dependencies as you find it is needed).

    4> Will the new application with pairing support needs reflash DFU or SOFT_DEVICE? or application/example.hex should be enough?

    There is no need to update the bootloader or SoftDevice just because you are introducing pairing or bonding.

  • Hello  

    Thank you for your last prompt response. It was really helpful and I could able to integrate peer_manager service in examples/ble_central/ble_app_uart_c and resolve all the compilation and linking issues.

    Now, I am getting BLE radio crash as soon as I try connecting the BLE sensor which supports pairing. I am yet to deep down line by line debugging from Segger Embedded Studio over Jlink but, 

    Any hint or guidance will be appreciated. 

    Below is the reference for how we have make sure the pairing is handled:

    #define STATIC_PASSKEY    "111111" 
    static ble_opt_t    m_static_pin_option;
    uint8_t passkey[] = STATIC_PASSKEY; 
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context){
    ...
            case BLE_GAP_EVT_AUTH_KEY_REQUEST:
                    err_code = sd_ble_gap_auth_key_reply(p_gap_evt->conn_handle, BLE_GAP_AUTH_KEY_TYPE_PASSKEY, &passkey[0]);
                    asm("nop");
                    APP_ERROR_CHECK(err_code);
                break;
    }

  • Hi,

    There are many other aspects that needs to be handled than the code snippet you have pasted here, but debugging is needed in order to know where and how things fail, so that we know where to look. The very first step could be to enable debug logging, then in most cases the issue would be caught by an APP_ERROR_CHECK(), and you could observe the log to see in which file and line number an error was detected.

    Another point, I was reading your question again now, and I am not sure if you need passkey entry support or not? You wrote something about "(with key:123456)" in the original question, but if your device does not have a means of inputting or displaying a key, it is probably better to set the I/O capabilities to BLE_GAP_IO_CAPS_NONE (no display and no buttons). (Using a static passkey does not give you better security compared to not using a passkey at all.)

  •   

    Apology for the confusions as it was a typo So you can read it as below.

    "Now, We have installed BLE pressure sensor on field which is only allowing characteristic/data read if it is paired (with key:111111)* and we got to know that NUS's ble_app_uart_c doesn't support pairing"

    When we connects first time to BLE pressure sensor from Ubuntu machine with the help of Bluetoothctl, we get characteristics data read access only after pairing it with key '111111' 

    When I had SEC params as below and tried to connect to BLE pressure sensor, got below error on segger

    #define SEC_PARAM_BOND              1                                   /**< Perform bonding. */
    #define SEC_PARAM_MITM              1                                   /**< Enable MITM protection */
    #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_KEYBOARD_ONLY       /**< Keyboard Only. */
    #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. */
    
    static void peer_manager_init(bool erase_bonds){
    ...
        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);
    }
        

    --------------------------- SEGGER LOGS -------------------------
    
    <info> ble_nus_c: Init BLE NUS UUID Type:2
    <debug> app: 
    <info> app: UART buffer: "ve" BVersion Info Request
    <debug> app: 
    <debug> ble_scan: Filter set on address type 1, address 0x
    <debug> ble_scan: 40
    <debug> ble_scan: 8A
    <debug> ble_scan: 67
    <debug> ble_scan: 90
    <debug> ble_scan: B1
    <debug> ble_scan: C5
    <debug> ble_scan: 
    
    <debug> ble_scan: Connecting
    <debug> ble_scan: Connection status: 0
    <info> app: BLE connected: Conected to Target MAC: 408A6790B1C5
    <debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
    <debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
    <error> app: ERROR 8 [NRF_ERROR_INVALID_STATE] at /home/*/Desktop/*/examples/ble_central/ble_app_uart_c/main.c:1087
    PC at: 0x0002B6A3
    <error> app: End of error report
    
    ------------------- LINE OF CODE NEAR BY CRASH -------------
    1079:                err_code = ble_db_discovery_start(&m_ble_db_discovery, m_pending_db_disc_conn);
    1080:            if (err_code == NRF_ERROR_BUSY)
    1081:            {
    1082:                printf("ble_db_discovery_start() returned busy, will retry later.\r\n");
    1083:                m_retry_db_disc = true;
    1084:            }
    1085:            else
    1086:            {
    1087:                APP_ERROR_CHECK(err_code);
    1088:            }

    But surprisingly as you suggested if I change SEC_PARAM_IO_CAPABILITIES as BLE_GAP_IO_CAPS_NONE instead of BLE_GAP_IO_CAPS_KEYBOARD_ONLY and perform the application upgrade, NRF BLE is stopped working as I am not able to interact with it from segger.

  • Hi,

    It seems that it is ble_db_discovery_start() that returned NRF_ERROR_INVALID_STATE, then? You can verify by debugging, but I assume that is from this check in the beginning of it's implementation:

        if (m_num_of_handlers_reg == 0)
        {
            // No user modules were registered. There are no services to discover.
            return NRF_ERROR_INVALID_STATE;
        }

    Which would typically be because ble_db_discovery_evt_register() have not been called, and this is called from for instance ble_nus_c_init(). Have you removed the NUS client and not added any other client implementations?

    Ankit Vaghasiya said:
    But surprisingly as you suggested if I change SEC_PARAM_IO_CAPABILITIES as BLE_GAP_IO_CAPS_NONE instead of BLE_GAP_IO_CAPS_KEYBOARD_ONLY and perform the application upgrade, NRF BLE is stopped working as I am not able to interact with it from segger.

    What does it mean that you are not able to interact with it from Segger?

Related