This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BLE_GATTS_EVT_WRITE in S110

hi, I an trying to enable notification from server. According to spec. i have to write 0x01 to the CCCD handle in heart rate characteristic in ble_app_hrs. In the BLE_GATTS_EVT_WRITE event they have called a fn on_hrm_cccd_write().

   static void on_hrm_cccd_write(ble_hrs_t * p_hrs, ble_gatts_evt_write_t * p_evt_write)
     {
      if (p_evt_write->len == 2)
     {
      // CCCD written, update notification state
      if (p_hrs->evt_handler != NULL)
      {
        ble_hrs_evt_t evt;

        if (ble_srv_is_notification_enabled(p_evt_write->data))
        {
            evt.evt_type = BLE_HRS_EVT_NOTIFICATION_ENABLED;
        }
        else
        {
            evt.evt_type = BLE_HRS_EVT_NOTIFICATION_DISABLED;
        }

        p_hrs->evt_handler(p_hrs, &evt);
      }
  }
}

But in the init function ble_hrs_init, p_hrs->evt_handler is set to NULL. And I could not find anywhere the handler is set. Then how the event handler specified in the last statement get called? Where is the actual write to CCCD is implemented? Am I making any wrong assumptions? I think I am missing something. Can anybody help me to find where I made mistake??

Thanks in advance.

  • If I understand the question correctly, you're wondering how/when the on_hrm_cccd_write is actually called?

    The handler is set further down in the main-file, in the ble_evt_dispatch function. This function is called from the BLE-stack whenever there is a ble-event. This is because in ble_stack_init, they call:

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);
    

    This tells the softdevice that whenever there is a ble-event, it should call ble_evt_dispatch

    ble_evt_dispatch looks like this:

    static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
    {
        dm_ble_evt_handler(p_ble_evt);
        ble_hrs_on_ble_evt(&m_hrs, p_ble_evt);
        ble_bas_on_ble_evt(&m_bas, p_ble_evt);
        ble_conn_params_on_ble_evt(p_ble_evt);
    
    #ifdef BLE_DFU_APP_SUPPORT    
        /** @snippet [Propagating BLE Stack events to DFU Service] */
        ble_dfu_on_ble_evt(&m_dfus, p_ble_evt);
        /** @snippet [Propagating BLE Stack events to DFU Service] */
    #endif // BLE_DFU_APP_SUPPORT    
        on_ble_evt(p_ble_evt);
    }
    

    So, when there is a ble event from the stack, that function will call ble_hrs_on_ble_evt, which calls on_write, which again calls on_hrm_cccd_write

    Hope that clarifies how the function is called!

  • I understood what you said. But my doubt is how the value 0x01 is written to CCCD of the peripheral? I could not find any API that will perform write to CCCD inside on_hrm_cccd_write something like sd_ble_gatts_value_set(). Instead it is calling one handler that is not defined anywhere. Can you please tell me p_hrs->evt_handler(p_hrs, &evt) (referred as the last statement inside the fuction) points to which event handler? I could not find where it is initialised.

  • Ah, i see what you mean! The actual value is updated by the softdevice itself, see for example this link for more info. The evt_handler you refer to looks like it's NULL, and never updated to be anything else.. It's a little strange I'll admit, but it isn't really needed in this case. I guess they have just made it easy for you if you want to implement your own event handler that performs some custom task when the cccd is written to.

  • Thank you for your reply.

Related