Zephyr equivalent for ble_link_ctx_manager

I'm currently porting an existing NRF SDK code base to NRF Connect SDK (Zephyr)..

Our existing code used ble_link_ctx_manager to maintain per connection state in a common service.  How should I do the same with zephyr? 

The sole use in this code base was for flags indicating which notifications were enabled. I can imagine this is important in cases where a device may maintain multiple connections and also support multiple notification characteristics related to multiple data sources.  One connected device may be interested in a certain subset of data while another device is interested in a different subset.  

With Zephyr it seems bt_gatt_notify sometimes checks the ccc value to determine if the notification is enabled, at least for the case where connection parameter is NULL.  Is it also true for a case where a specific connection is indicated or is it necessary for the application to check the ccc state?  

Is it only necessary to track the ccc state in parallel with the BT controller when that state is by the app for example ot activate a sensor when 1 or more connections requests the notifications?

  • Hi Anthony,

    When moving from the nRF5 SDK to nRF Connect SDK, there is no point to point similar functions that are present. So in order to manage per-connection state for GATT services like notification flags (which you previously handled with ble_link_ctx_manager), you can take a look at the Zephyr APIs and utilize a combination of those in order to get your required functionality.

    Please take a look at the GATT service APIs in Zephyr: https://docs.zephyrproject.org/apidoc/latest/group__bt__gatt__server.html 

    You have the  CCC (Client Characteristic Configuration) Descriptors in Zephyr which you can use. 

    Regards,

    Priyanka 

  • I'm reading the implementation of gatt.c in zephyr, and I find it very strange.  If I have multiple connections active at the same time my GATT server should operate for each client according to the client's ccc configuration.

    It appears the gatt.c ccc changed function treats callback would only fire in a couple of cases:

    * when all clients were 0 and then 1 client becomes non-zero

    * if only 1 client were non-zero and then it becomes zero

    In all other cases the ccc_changed callback would not fire since the combined value doesn't really change.  Also when I receive the ccc_changed callback there is no indication of which client changed.  It all seems to be designed around a use case of a single connection.

    Honestly this sort of worries me, previously nordic's SDK was the main reason I recommended my client's to use your products.  That SDK has been abandoned and the replacement seems to be incomplete and faulty.

  • Zephyr's CCC callback implementation is only useful for very simple cases.  In my use cases I have to replace code in zephyr's GATT implementation to get per connection value change callbacks.  

    Zephyr's per peer link context is distributed throughout the GATT on each characteristic.  I haven't yet determined whether they GATT state is preserved as it was with NRF SDK, I suspect there is a flag option to do this.

    In general the best way to get the per peer value of a ccc is to call:

    bool bt_gatt_is_subscribed(struct bt_conn *conn, const struct bt_gatt_attr *attr, uint16_t ccc_type);

    A more detailed discussion about ccc callbacks can be found here:

    github.com/.../79822

Related