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

Determining if DFU occurred

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 be called, but how should I determine if a DFU has just been performed?

  • 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:

    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(&end_handle);
        ASSERT(err_code == NRF_SUCCESS);
    
        for (uint16_t handle = 1; handle < end_handle; handle++)
        {
            ble_uuid_t uuid;
            err_code = sd_ble_gatts_attr_get(handle, &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("Found char at handle %d", 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, &characteristic_decl);
                VERIFY_SUCCESS(err_code);
                if(characteristic_decl.len != decl_val_size)
                {
                    continue;
                }
                uint16_t char_uuid = *((uint16_t *)&decl_val[3]);
                sc_found = char_uuid == BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED;
                // skip past characteristic value handle
                handle = *((uint16_t *)&decl_val[1]);
                NRF_LOG_DEBUG("Skipping past val handle to %d (%s)", handle+1, sc_found ? "sc found" : "sc not found");
            }
            else if(sc_found && (uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG))
            {
                NRF_LOG_DEBUG("Found cccd at handle %d", 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, &cccd_val);
            }
        }
        NRF_LOG_DEBUG("Did not find service changed CCCD");
        return NRF_ERROR_NOT_FOUND;
    }

Related