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

How do I know if my CCCD handles is set and how many CCCD handles usually are there?

Sorry that I'm asking 2 questions in one go, but they are closely related.

Problem: got 0x00000008, INVALID_STATE error when calling sd_ble_gatts_hvx, looked it up, it's most likely CCCD not set.

The thing is I've been migrating from nrf51 to 52, and the code worked back in nrf51, and I'm very very sure that my Android program set the CCCD which enabled the notification.

And now after moved to nrf52840 @s140, it's not working so well, so I'm asking:

  1. how do I verify using keil's debug mode, that the cccd is really set? My memory is kind of fuzzy, I used the nrf panel or something which was too much hassel to use.

  2. how many cccd handles are there? I may have more than 1, I'm completely unsure, but based on my impression, there should be only 1 per connection? Or maybe there are 1 per attribute? Can't remember.

  • Hi Mitch,

    This mechanism hasn't changed since original nRF51 Soft Devices:

    • When you are provisioning GATT Server role and you have any Characteristic with Notifications or Indications enabled you will automatically get handle numbers for both Value and CCCD handles. This will happen for any such Characteristic (because every such Characteristic has its own CCCD - as explained in BT SIG spec). See p_handles parameter of sd_ble_gatts_characteristic_add for more details.
    • Once you get any GAP Peripheral connection you will in your GATT Server event handler watch for Write events. Once you (from event data) see that Write targets one of CCCDs and it contains value (typically 16 bits) which enable particular Notification or Indication method you can start using it. Otherwise if you try and method is not enabled you get error as you do in your example right now.

    There is even nice function for it in nRF5 SDK V13.0.0 examples\ble_peripheral\ble_app_pwr_profiling\main.c example:

    /**@brief Function for evaluating the value written in CCCD
     *
     * @details This shall be called when there is a write event received from the stack. This
     *          function will evaluate whether or not the peer has enabled notifications and
     *          start/stop notifications accordingly.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     */
    static void on_write(ble_evt_t * p_ble_evt) {
        ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
        if ((p_evt_write->handle == m_char_handles.cccd_handle) && (p_evt_write->len == 2)) {
            // CCCD written. Start notifications
            m_is_notifying_enabled = ble_srv_is_notification_enabled(p_evt_write->data);
    
            if (m_is_notifying_enabled) {
                // Start using HVX here...
    
            }
            // ...
        }
    }
    

    To your questions:

    1. I don't think there would be any real-time (run-time) access to GATT Server emulation inside Soft Device so I don't think you could read this from any offset or variable during debug of your application code. However when reading S13x/S140 GATTS API it looks like calling sd_ble_gatts_value_get(...) any time you are unsure will give you desired CCCD value (you just need to say which Connection handle and (G)ATT handle you want to read, therefore you need to remember CCCD handle value from GATTS provisioning as explained above).
    2. This is answered above.

    Cheers Jan

  • Hello @endnode, this is the 3rd time I'm reading your answer, and I tried out the function you recommended, regrettably it didn't work exactly the way I anticipated it...could you please take a look at this question?

Related