<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Determining if DFU occurred</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/51672/determining-if-dfu-occurred</link><description>After a DFU, when the new firmware is booted a service changed indication is not being sent so iOS only sees the DFU service. Should the softdevice be sending the service changed indication automatically? Here it says pm_local_database_has_changed() should</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 04 Sep 2019 10:44:03 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/51672/determining-if-dfu-occurred" /><item><title>RE: Determining if DFU occurred</title><link>https://devzone.nordicsemi.com/thread/207886?ContentTypeID=1</link><pubDate>Wed, 04 Sep 2019 10:44:03 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:aada589a-382b-483d-b089-f7f3a6eac9db</guid><dc:creator>nrbrook</dc:creator><description>&lt;p&gt;Here is some improved code which uses the UUIDs of the attributes instead of assuming the location of the CCCD relative to the characteristic declaration:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;static ret_code_t service_changed_cccd(uint16_t conn_handle, const uint16_t * p_cccd)
{
    uint16_t   end_handle;
    bool sc_found = false;
    ret_code_t err_code = sd_ble_gatts_initial_user_handle_get(&amp;amp;end_handle);
    ASSERT(err_code == NRF_SUCCESS);

    for (uint16_t handle = 1; handle &amp;lt; end_handle; handle++)
    {
        ble_uuid_t uuid;
        err_code = sd_ble_gatts_attr_get(handle, &amp;amp;uuid, NULL);
        VERIFY_SUCCESS(err_code);
        if(uuid.type != BLE_UUID_TYPE_BLE)
        {
            continue;
        }
        if(uuid.uuid == BLE_UUID_CHARACTERISTIC)
        {
            // characteristic declaration specification from Bluetooth 4.0 Vol 3 3.3.1
            static const uint8_t decl_val_size = 5;
            NRF_LOG_DEBUG(&amp;quot;Found char at handle %d&amp;quot;, handle);
            // get characteristic declaration
            uint8_t decl_val[decl_val_size];
            ble_gatts_value_t characteristic_decl = {.p_value = decl_val, .len = decl_val_size, .offset = 0};
            err_code = sd_ble_gatts_value_get(conn_handle, handle, &amp;amp;characteristic_decl);
            VERIFY_SUCCESS(err_code);
            if(characteristic_decl.len != decl_val_size)
            {
                continue;
            }
            uint16_t char_uuid = *((uint16_t *)&amp;amp;decl_val[3]);
            sc_found = char_uuid == BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED;
            // skip past characteristic value handle
            handle = *((uint16_t *)&amp;amp;decl_val[1]);
            NRF_LOG_DEBUG(&amp;quot;Skipping past val handle to %d (%s)&amp;quot;, handle+1, sc_found ? &amp;quot;sc found&amp;quot; : &amp;quot;sc not found&amp;quot;);
        }
        else if(sc_found &amp;amp;&amp;amp; (uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG))
        {
            NRF_LOG_DEBUG(&amp;quot;Found cccd at handle %d&amp;quot;, handle);
            ble_gatts_value_t cccd_val = {.p_value = (uint8_t *)p_cccd, .len = 2, .offset = 0};
            return sd_ble_gatts_value_get(conn_handle, handle, &amp;amp;cccd_val);
        }
    }
    NRF_LOG_DEBUG(&amp;quot;Did not find service changed CCCD&amp;quot;);
    return NRF_ERROR_NOT_FOUND;
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining if DFU occurred</title><link>https://devzone.nordicsemi.com/thread/207815?ContentTypeID=1</link><pubDate>Wed, 04 Sep 2019 08:09:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:579a78bb-e981-4f48-b32a-f45a1eb52064</guid><dc:creator>nrbrook</dc:creator><description>&lt;p&gt;Yes, 15.3.0&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining if DFU occurred</title><link>https://devzone.nordicsemi.com/thread/207804?ContentTypeID=1</link><pubDate>Wed, 04 Sep 2019 07:37:42 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d976cc14-6942-4dda-8409-db71c9d8f8d8</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Thank you for letting us know. Which SDK version have you used for the change, SDK 15.3?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining if DFU occurred</title><link>https://devzone.nordicsemi.com/thread/207746?ContentTypeID=1</link><pubDate>Tue, 03 Sep 2019 17:49:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:bbafc008-5e77-4f91-8518-7e2fd5459e30</guid><dc:creator>nrbrook</dc:creator><description>&lt;p&gt;After further investigation,&lt;/p&gt;
&lt;p&gt;If&amp;nbsp;NRF_ERROR_INVALID_STATE occurs, on line 364 of gatt_cache_manager.c, the state of the service changed CCCD&amp;nbsp;is determined. However, if the client has not subscribed, then it falls through to&amp;nbsp;NRF_ERROR_NOT_SUPPORTED, which cancels the indication for this peer. I am not sure if this is correct, but perhaps it is as perhaps the invalid state error does not occur if the client is not subscribed.&lt;/p&gt;
&lt;p&gt;In my case, indications are enabled at this point. However, the&amp;nbsp;service_changed_cccd function does not work correctly. It uses&amp;nbsp;sd_ble_gatts_value_get which returns the value of an attribute handle, not its UUID. I don&amp;#39;t think there is a way to get the UUID of an attribute. However, the purpose of the function can be achieved with the following code. After changing to this, indications work.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static ret_code_t service_changed_cccd(uint16_t conn_handle, const uint16_t * p_cccd)
{
    uint16_t   end_handle;
    ret_code_t err_code = sd_ble_gatts_initial_user_handle_get(&amp;amp;end_handle);
    ASSERT(err_code == NRF_SUCCESS);

    for (uint16_t handle = 1; handle &amp;lt; end_handle; handle++)
    {
        uint16_t uuid;
        ble_gatts_value_t value = {.p_value = (uint8_t *)&amp;amp;uuid, .len = 2, .offset = 3};
        err_code = sd_ble_gatts_value_get(conn_handle, handle, &amp;amp;value);
        if(err_code == NRF_ERROR_INVALID_PARAM)
        {
            // the offset was not valid for this attribute
            continue;
        }
        else if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        else if (uuid == BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED)
        {
             ble_gatts_value_t cccd_val = {.p_value = (uint8_t *)p_cccd, .len = 2, .offset = 0};
            return sd_ble_gatts_value_get(conn_handle, handle+2, &amp;amp;cccd_val);
        }
    }
    return NRF_ERROR_NOT_FOUND;
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining if DFU occurred</title><link>https://devzone.nordicsemi.com/thread/207738?ContentTypeID=1</link><pubDate>Tue, 03 Sep 2019 16:48:56 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c4e79c3d-37d3-4b06-96ec-55e9f861522f</guid><dc:creator>nrbrook</dc:creator><description>&lt;p&gt;So I&amp;#39;ve implemented this, calling&amp;nbsp;&lt;a href="https://www.nordicsemi.com/DocLib/Content/SDK_Doc/nRF5_SDK/v15-2-0/group__peer__manager?3990#gaaecb7f99f58d71f085f62f5cc5267508"&gt;pm_local_database_has_changed()&lt;/a&gt;&amp;nbsp;on boot when the application version has changed. This bit works correctly. This function stores flags for each bonded device to track if service changed has been sent. On connection, this indication is sent immediately &amp;ndash; before the service changed characteristic has had indications enabled. The call to&amp;nbsp;sd_ble_gatts_service_changed returns&amp;nbsp;NRF_ERROR_INVALID_STATE. However,&amp;nbsp;BLE_GATTS_EVT_SC_CONFIRM still occurs, so the service changed indication is stored as sent and is not sent again. I think this is a bug?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining if DFU occurred</title><link>https://devzone.nordicsemi.com/thread/207494?ContentTypeID=1</link><pubDate>Mon, 02 Sep 2019 18:57:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b031d28c-1764-44d7-91ce-b5fb1f97ea22</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Good question. This is not handled by any example so it is up to you how to do it. This could be done in several ways, but one possible way (off the top of my head):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The firmware version is stored in the bootoader settings page, and can therefor be read from the application.&lt;/li&gt;
&lt;li&gt;Use FDS (or other method) to store persistently in flash which firmware version is used when a bond is made to a peer device.&lt;/li&gt;
&lt;li&gt;When connecting to a peer, search for a FDS record of that peer indicating the firmware version.
&lt;ul&gt;
&lt;li&gt;If the firmware version matches the current version, do nothing.&lt;/li&gt;
&lt;li&gt;If the firmware version does not match the current version, indicate service changed and update the FDS record to have the value of the current firmware version.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>