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

How to use sd_ble_gatts_service_changed?

In our product we have both a DFU profile and an application profile which is confusing Mac OS X 10.9 "Mavericks" since it caches device services unless it receives a service changed indication.

The sd_ble_gatts_service_changed requires a start and end service handle, is there a way to determine what the max used service handle is? Passing 0xFF as max causes the routine to return an error.

  • Part of the problem here stems from the fact that you need to send invalidations for the service handles that the app uses from the bootloader and vice-versa. The app and the bootloader don't have the same number of handles and therefore the function call as it is currently implemented will refuse to send the invalidations.

  • Hi John, could you check what error code that you receive? The start handle should be greater than the service changed cccd handle (0x0B), so you could try to set the start handle to 0x0C and end handle to 0xFFFF should not be any issue.

  • I believe it was 15. Will try 0x0C-0xFFFF sand report back

  • Hi Pål,

    I’m working with John on this problem. We’ve tried setting the start_handle/end_handle for the function to 0x000C-0xFFFF and it now returns a different error code: NRF_ERROR_INVALID_STATE “Invalid state to perform operation, notifications or indications must be enabled in the CCCD.”

    Presumably this means that indications/notifications must be enabled on the CCCD for the Service Changed characteristic itself (UUID 0x2A05). However, I don’t know how to access the handle for Service Changed CCCD to enable indications.

    As far as I know, the Service Changed Characteristic is UUID 0x2A05, and should be added to the Generic Attribute Service (UUID 0x1801). However, I cannot use sd_ble_gatts_service_add() to add a service with UUID 0x1801. If I do, I get an error code of NRF_ERROR_FORBIDDEN: “Forbidden value supplied, certain UUIDs are reserved for the stack.”

    I’m now at a bit of a loss what to do. Is it possible to send us some sample code that simply (1) waits for a connection from a client, and then (2) sends a service changed indication?

    Thanks!

  • Hi Andre,

    As far as I can remember, the OS X and iOS would always check for a Service Changed characteristic and enable this for every connection if you do not bond, and only once if you bond.

    The Service Changed characteristic is added by default in the stack, and you should not have to think about adding it yourself.

    The NRF_ERROR_INVALID_STATE might happen because you respond to a BLE_GATTS_EVT_SYS_ATTR_MISSING (using a sd_ble_gatts_sys_attrs_set with NULL), thus disabling all the CCCD's.

    After the first time you bonded, you should use the sd_ble_gatts_sys_attrs_get function to retrieve all the cccd's that have been set by the peer (Preferable when you receive the disconnected event). This should be stored in flash or any other place where it is retrievable by your application after it has been upgraded.

    When you re-connect again you should call the sd_ble_gatts_sys_attrs_set function with the stored system attributes. This would enable all those CCCD's that the peer had already enabled. (Like the Service Changed CCCD) and you should be able to send a Service Changed to the peer.

Related