Skip to content

Commit

Permalink
Merge pull request #89 from PelionIoT/release-4.10.0
Browse files Browse the repository at this point in the history
mbed-cloud-client 4.10.0
  • Loading branch information
teetak01 committed Jul 8, 2021
2 parents 7e45d92 + e526be9 commit d7edc52
Show file tree
Hide file tree
Showing 94 changed files with 3,251 additions and 1,364 deletions.
50 changes: 48 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,60 @@
## Changelog for Pelion Device Management Client

### Release 4.10.0 (07.07.2021)

### Device Management Client

- Updated Mbed CoAP to v5.1.11.
- Improved handling of "Bad requests" during bootstrapping. Now client will handle the recovery internally without reporting fatal certificate errors to upper level.
- Previously this was resulting in factory resets as this was handled as fatal storage failure.
- Fixed duplication of sent notifications, which sometimes happened if the application called `set_value()`in the `MbedCloudClient::on_registered()`callback.
- Added sleep state for `MbedCloudClient::on_status_changed()`.

This makes `MbedCloudClient::set_queue_sleep_handler(callback_handler handler)` redundant. It's marked as deprecated.

- Added support for LwM2M Discover.
- Allowed the application to control the maximum reconnection timeout using the `MBED_CONF_MBED_CLIENT_MAX_RECONNECT_TIMEOUT` flag.

This flag ensures that the reconnection time doesn't go above the set maximum value. The default value is 4hrs, and the lowest acceptable value is 5min.

#### Device Management Update Client

- Added support for updating device firmware with a server-encrypted update image.
- Enabled by the new `MBED_CLOUD_CLIENT_FOTA_ENCRYPTION_SUPPORT` macro.
- Limitation: Not supported when `MBED_CLOUD_CLIENT_FOTA_CANDIDATE_BLOCK_SIZE` is not 1024.
- Changes to implementation of update candidate image encryption:
- Added a new `FOTA_USE_ENCRYPTED_ONE_TIME_FW_KEY` option to the `MBED_CLOUD_CLIENT_FOTA_KEY_ENCRYPTION` macro.
- Replaced `FOTA_USE_DEVICE_KEY` with `FOTA_USE_ENCRYPTED_ONE_TIME_FW_KEY` as the default value for `MBED_CLOUD_CLIENT_FOTA_KEY_ENCRYPTION` following a security vulnerability found in `FOTA_USE_DEVICE_KEY`.

<div style="background-color:#F3F3F3; text-align:left; vertical-align: middle; padding:15px 30px;">
For Mbed OS devices, using `FOTA_USE_ENCRYPTED_ONE_TIME_FW_KEY` is a breaking change that requires the new bootloader introduced in Device Management Client 4.10.0.

In Device Management Client 4.10.0, `FOTA_USE_ENCRYPTED_ONE_TIME_FW_KEY` is the default value of the `MBED_CLOUD_CLIENT_FOTA_KEY_ENCRYPTION` macro.

If you are upgrading to Device Management Client 4.10.0 but using the bootloader from a previous release, you must explicitly define `FOTA_USE_DEVICE_KEY`.

We highly recommend using the bootloader from Device Management Client 4.10.0, which fixes a security vulnerability found in the bootloader from the 4.8.0/4.9.0 releases.
</div>

- Deprecated the `FOTA_USE_DEVICE_KEY` option, which will be removed in a future version.
- Changed `fota_app_defer()` behavior so that candidate image download or install resumes only after the device application explicitly calls `fota_app_resume()`. When the device reboots, the client invokes the download or install callbacks to request the device application’s approval to continue the download or installation.
- Added support for calling `fota_app_reject()` after `fota_app_defer()`.
- Added the `fota_app_postpone_reboot()` API. Calling this API postpones device reboot, which is required to complete the FOTA process, until the device application explicitly initiates reboot.
- Fix: Resuming download from the last successfully downloaded fragment was not previously supported on devices with an SD card, like the K64F.
- Fix: Support for resuming installation after an unexpected interruption (for example, power loss):
- Of the main or component image on Linux.
- Of a component image on an Mbed OS devices.
- Fix: Removed the candidate image file from its original path in Linux after FOTA completion.

### Release 4.9.1 (17.06.2021)

### Device Management Client
- Fixed the incorrect overriding of CoAP retransmission buffer size.

### Platform Adaptation Layer (PAL)
- [Zephyr] Fixed a memory leak on DNs handling.
- [Zephyr] Fixed a memory leak on DNS handling.

### Release 4.9.0 (20.05.2021)
### Release 4.9.0 (21.05.2021)

### Device Management Client

Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Due to the release process, all new releases are squashed code drops. Therefore,

| Author | Pull Request | Change title/summary |
|----------------|---------------|----------------------------------------------------------|
| Garrett LoVerde (@40Grit) | [#46](https://github.com/ARMmbed/mbed-cloud-client/pull/46) | Remove redundant switch in `get_resource` |
| Garrett LoVerde (@40Grit) | [#46](https://github.com/PelionIoT/mbed-cloud-client/pull/46) | Remove redundant switch in `get_resource` |
| Pawel Dunaj ([@pdunaj](https://github.com/pdunaj)) | N/A | Port Pelion Client to Zephyr OS |
| Emil Obalski ([@emob-nordic](https://github.com/emob-nordic)) | N/A | Port Pelion Client to Zephyr OS |
| Emil Obalski ([@emob-nordic](https://github.com/emob-nordic)) | [#86](https://github.com/PelionIoT/mbed-cloud-client/pull/86) | Update pal Timers |
64 changes: 32 additions & 32 deletions DOXYGEN_FRONTPAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ The C++ API allows quick application development.

Device Management Client C++ API is essentially constructed around following classes, their base classes and derivatives:

* MbedCloudClient
* M2MInterface
* M2MObject
* M2MObjectInstance
* M2MResource
* M2MResourceInstance
* MbedCloudClient.
* M2MInterface.
* M2MObject.
* M2MObjectInstance.
* M2MResource.
* M2MResourceInstance.

Device Management Client follows the architecture specified by LwM2M.
`M2MObject`, `M2MObjectInstance`, `M2MResource`, `M2MResourceInstance` are C++ classes that represent what LwM2M specifies as *Object*, *Object Instance*, *Resouce* and *Resource Instance*.
Expand Down Expand Up @@ -65,41 +65,41 @@ This process shows how you can create a client-based application.

1. Create a `MbedCloudClient` object and register certain callbacks with it:

```.cpp
MbedCloudClient client;
client.on_registered(...);
client.on_unregistered(...);
client.on_error(...);
```
```.cpp
MbedCloudClient client;
client.on_registered(...);
client.on_unregistered(...);
client.on_error(...);
```

1. Define your own resources:
2. Define your own resources:

```.cpp
M2MObjectList list;
```.cpp
M2MObjectList list;

M2MObject *object = M2MInterfaceFactory::create_object(name);
M2MObjectInstance* object_instance = object->create_object_instance(instance_id);
M2MResource* resource = object_instance->create_dynamic_resource(name, resource_type, data_type, observable);
M2MObject *object = M2MInterfaceFactory::create_object(name);
M2MObjectInstance* object_instance = object->create_object_instance(instance_id);
M2MResource* resource = object_instance->create_dynamic_resource(name, resource_type, data_type, observable);

resource->set_value((const unsigned char*)value, strlen(value));
resource->set_operation(M2MBase::GET_PUT_ALLOWED);
resource->set_message_delivery_status_cb(...);
resource->set_value_updated_function((void(*)(const char*))cb);
resource->set_value((const unsigned char*)value, strlen(value));
resource->set_operation(M2MBase::GET_PUT_ALLOWED);
resource->set_message_delivery_status_cb(...);
resource->set_value_updated_function((void(*)(const char*))cb);

list->push_back(object);
```
list->push_back(object);
```
1. Call `MbedCloudClient::add_objects()` to add LwM2M objects to the client:
3. Call `MbedCloudClient::add_objects()` to add LwM2M objects to the client:
```.cpp
client.add_objects(_obj_list);
```
```.cpp
client.add_objects(_obj_list);
```

1. Give a platform-specific pointer to the client (it uses this as its network interface):
4. Give a platform-specific pointer to the client (it uses this as its network interface):

```.cpp
client.setup(mcc_platform_get_network_interface());
```
```.cpp
client.setup(mcc_platform_get_network_interface());
```

This initiates the client and starts its state machine.

Expand Down
10 changes: 5 additions & 5 deletions device-sentry-client/source/linux-os/ds_linux_metrics_report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ static ds_status_e extract_ip_addr_and_port(const char *rem_address_field, ds_st

static bool avoid_report_remote_address(const char *rem_address_field, int connection_state_field, ds_net_protocol_type_t protocol)
{
SA_PV_ERR_RECOVERABLE_RETURN_IF((rem_address_field == NULL), DS_STATUS_INVALID_PARAMETER, "Invalid parameter: rem_address_field is NULL");
SA_PV_ERR_RECOVERABLE_RETURN_IF((rem_address_field == NULL), true, "Invalid parameter: rem_address_field is NULL");
SA_PV_LOG_TRACE_FUNC_ENTER("rem_address_field=%s, connection_state_field=%d, protocol=%d", rem_address_field, connection_state_field, protocol);

bool ret_var = false;
Expand Down Expand Up @@ -366,9 +366,9 @@ static const char* protocol_to_str(ds_net_protocol_type_t protocol)

static bool is_ip_addr_and_port_already_reported(const ds_stat_ip_data_t *stats_array, uint32_t number_items_to_search, const ds_stat_ip_data_t* ip_data)
{
SA_PV_ERR_RECOVERABLE_RETURN_IF((ip_data == NULL), DS_STATUS_INVALID_PARAMETER, "Invalid parameter: ip_data is NULL");
SA_PV_ERR_RECOVERABLE_RETURN_IF((ip_data == NULL), true, "Invalid parameter: ip_data is NULL");
SA_PV_LOG_TRACE_FUNC_ENTER("ip address=%s, port=%" PRIu16, ip_data->ip_addr, ip_data->port);
SA_PV_ERR_RECOVERABLE_RETURN_IF((stats_array == NULL), DS_STATUS_INVALID_PARAMETER, "Invalid parameter: stats_array is NULL");
SA_PV_ERR_RECOVERABLE_RETURN_IF((stats_array == NULL), true, "Invalid parameter: stats_array is NULL");

bool ret_var = false;
for (uint32_t i = 0; i <= number_items_to_search; i++) {
Expand Down Expand Up @@ -567,10 +567,10 @@ ds_status_e ds_plat_memory_stats_get(ds_stats_memory_t *mem_stats_out)

uint64_t mem_total_kb = 0, mem_free_kb = 0;
ds_status_e status = meminfo_fields_get_from_line(&mem_total_kb, "MemTotal:", fp);
SA_PV_ERR_RECOVERABLE_GOTO_IF((status != DS_STATUS_SUCCESS), status, release_resources, "Failed to get MemTotal field");
SA_PV_ERR_RECOVERABLE_GOTO_IF((status != DS_STATUS_SUCCESS), (void)status, release_resources, "Failed to get MemTotal field");

status = meminfo_fields_get_from_line(&mem_free_kb, "MemFree:", fp);
SA_PV_ERR_RECOVERABLE_GOTO_IF((status != DS_STATUS_SUCCESS), status, release_resources, "Failed to get MemFree field");
SA_PV_ERR_RECOVERABLE_GOTO_IF((status != DS_STATUS_SUCCESS), (void)status, release_resources, "Failed to get MemFree field");

release_resources:
fclose (fp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ kcm_status_e psa_drv_crypto_get_handle(uint16_t key_id, psa_key_handle_t *key_ha
//Open key handle
psa_status = psa_open_key(key_id, key_handle_out);
SA_PV_ERR_RECOVERABLE_RETURN_IF((psa_status != PSA_SUCCESS), psa_drv_translate_to_kcm_error(psa_status), "Failed to open the key");
SA_PV_LOG_TRACE("psa_open_key %" PRIu32 " handle %" PRIu32 "", key_id, key_handle_out);
#else
uint32_t extra_flags;
uint8_t raw_key[KCM_EC_SECP256R1_MAX_PUB_KEY_RAW_SIZE + sizeof(extra_flags)]; // should be bigger than KCM_EC_SECP256R1_MAX_PRIV_KEY_RAW_SIZE
Expand Down
41 changes: 28 additions & 13 deletions factory-configurator-client/storage/source/key_slot_allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,21 @@ static kcm_status_e store_table(ksa_descriptor_s *table_descriptor)
kcm_status_e kcm_status = KCM_STATUS_SUCCESS;

SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
//#define PRINT_KSA_TABLE
#ifdef PRINT_KSA_TABLE
if(table_descriptor->ksa_table_uid == KSA_KEY_TABLE_ID_RESERVED_TYPE) {
printf("table id %d\n", table_descriptor->ksa_table_uid);
printf("| item name | active id | factory id | renewal id |\n");
for(int i = 0; i < table_descriptor->ksa_num_of_table_entries; i++) {
printf("| %x | %d | %d | %d |", table_descriptor->ksa_start_entry[i].item_name,
table_descriptor->ksa_start_entry[i].active_item_id,
table_descriptor->ksa_start_entry[i].factory_item_id,
table_descriptor->ksa_start_entry[i].renewal_item_id);

printf("\n");
}
}
#endif

//Save the new table
kcm_status = psa_drv_ps_set_data_direct(table_descriptor->ksa_table_uid, (const void*)table_descriptor->ksa_start_entry,
Expand Down Expand Up @@ -314,11 +329,11 @@ static void destroy_ksa_tables()
}


static kcm_status_e set_entry_id(ksa_item_entry_s *item_entry, ksa_id_type_e item_id_type, uint16_t id_value)
static kcm_status_e set_entry_id(ksa_item_entry_s *item_entry, ksa_id_type_e item_id_type, uint16_t id_value, ksa_item_type_e table_index)
{
kcm_status_e kcm_status = KCM_STATUS_SUCCESS;

SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
SA_PV_LOG_TRACE_FUNC_ENTER("id type %" PRIu32 ", id value %" PRIu16 "", (uint32_t)item_id_type, id_value);

SA_PV_ERR_RECOVERABLE_RETURN_IF((item_entry == NULL), KCM_STATUS_INVALID_PARAMETER, "table_entry is NULL");

Expand All @@ -338,7 +353,7 @@ static kcm_status_e set_entry_id(ksa_item_entry_s *item_entry, ksa_id_type_e ite
}

//Save the table
kcm_status = store_table(&g_ksa_desc[item_id_type]);
kcm_status = store_table(&g_ksa_desc[table_index]);
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to store KSA table to persistent store");

SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
Expand Down Expand Up @@ -422,7 +437,7 @@ static kcm_status_e destroy_all_ce_keys()
kcm_status = delete_data(table_entry->renewal_item_id);
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS && kcm_status != KCM_STATUS_INVALID_PARAMETER), kcm_status, "Failed to destroy key id");
//zero the entry
set_entry_id(table_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID);
set_entry_id(table_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID, KSA_KEY_ITEM);
}
table_entry++;
}
Expand Down Expand Up @@ -1159,7 +1174,7 @@ kcm_status_e ksa_factory_reset(void)
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed destroying CE item ");

//zero the entry
set_entry_id(table_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID);
set_entry_id(table_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID, table_index);
}

//squeeze the entry, if it became empty after factory reset - e.g both active and factory entries are 0
Expand Down Expand Up @@ -1393,12 +1408,12 @@ kcm_status_e ksa_generate_ce_keys(
kcm_status = psa_drv_crypto_generate_keys_from_existing_ids(prv_ksa_id, pub_ksa_id, &prv_ksa_id, &pub_ksa_id, psa_priv_key_handle, psa_pub_key_handle);
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to generate keys");

kcm_status = set_entry_id(priv_key_entry, KSA_CE_PSA_ID_TYPE, prv_ksa_id);
kcm_status = set_entry_id(priv_key_entry, KSA_CE_PSA_ID_TYPE, prv_ksa_id, KSA_KEY_ITEM);
SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed to set_entry_id");

if (public_key_name != NULL) {

kcm_status = set_entry_id(pub_key_entry, KSA_CE_PSA_ID_TYPE, pub_ksa_id);
kcm_status = set_entry_id(pub_key_entry, KSA_CE_PSA_ID_TYPE, pub_ksa_id, KSA_KEY_ITEM);
SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed to set_entry_id");
}

Expand All @@ -1409,12 +1424,12 @@ kcm_status_e ksa_generate_ce_keys(
//In case of error we need to close and destroy allocated key handles
if (psa_priv_key_handle != 0) {
psa_destroy_key(*psa_priv_key_handle);
set_entry_id(priv_key_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID);
set_entry_id(priv_key_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID, KSA_KEY_ITEM);
*psa_priv_key_handle = 0;
}
if (psa_pub_key_handle != 0) {
psa_destroy_key(*psa_pub_key_handle);
set_entry_id(pub_key_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID);
set_entry_id(pub_key_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID, KSA_KEY_ITEM);
*psa_pub_key_handle = 0;
}
}
Expand Down Expand Up @@ -1455,7 +1470,7 @@ kcm_status_e ksa_destroy_ce_key(const uint8_t *item_name, uint32_t item_type)
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS && kcm_status != KCM_STATUS_INVALID_PARAMETER), kcm_status, "Failed to destroy key id");

//Clean the current id field
kcm_status = set_entry_id(ksa_key_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID);
kcm_status = set_entry_id(ksa_key_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID, ksa_item_type);
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to update active id");

kcm_status = store_table(&g_ksa_desc[item_type]);
Expand Down Expand Up @@ -1544,11 +1559,11 @@ kcm_status_e ksa_activate_ce_key(const uint8_t *key_name)
SA_PV_ERR_RECOVERABLE_RETURN_IF((table_entry->renewal_item_id == 0), kcm_status = KCM_STATUS_ITEM_NOT_FOUND, "Renewal ID is not valid");

//Update active id of the entry with value of renewal id
kcm_status = set_entry_id(table_entry, KSA_ACTIVE_PSA_ID_TYPE, table_entry->renewal_item_id);
kcm_status = set_entry_id(table_entry, KSA_ACTIVE_PSA_ID_TYPE, table_entry->renewal_item_id, KSA_KEY_ITEM);
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to update active id");

// default renewal id
kcm_status = set_entry_id(table_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID);
kcm_status = set_entry_id(table_entry, KSA_CE_PSA_ID_TYPE, PSA_INVALID_SLOT_ID, KSA_KEY_ITEM);
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to zero renewal id");

SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
Expand Down Expand Up @@ -1643,7 +1658,7 @@ kcm_status_e ksa_update_key_id(const uint8_t *key_name, ksa_id_type_e key_id_typ
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed get_active_entry_of_existing_item");

//Update active id of the entry with value of renewal id
kcm_status = set_entry_id(table_entry, key_id_type, id_value);
kcm_status = set_entry_id(table_entry, key_id_type, id_value, KSA_KEY_ITEM);
SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to update active id");

SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
Expand Down
2 changes: 1 addition & 1 deletion factory-configurator-client/storage/source/storage_psa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ kcm_status_e storage_key_get_handle(
SA_PV_ERR_RECOVERABLE_RETURN_IF((key_type != KCM_PRIVATE_KEY_ITEM && key_type != KCM_PUBLIC_KEY_ITEM), KCM_STATUS_INVALID_PARAMETER, "key type not supported");
SA_PV_ERR_RECOVERABLE_RETURN_IF((key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid key_name");
SA_PV_ERR_RECOVERABLE_RETURN_IF((key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid key_name_len");
SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 "", (int)key_name_len, (char*)key_name, (uint32_t)key_name_len);
SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 " type %" PRIu32 "", (int)key_name_len, (char*)key_name, (uint32_t)key_name_len, (uint32_t)item_prefix_type);
SA_PV_ERR_RECOVERABLE_RETURN_IF((item_prefix_type != STORAGE_ITEM_PREFIX_KCM && item_prefix_type != STORAGE_ITEM_PREFIX_CE), KCM_STATUS_INVALID_PARAMETER, "Invalid key_source_type");
SA_PV_ERR_RECOVERABLE_RETURN_IF((key_type != KCM_PRIVATE_KEY_ITEM && key_type != KCM_PUBLIC_KEY_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid key type");
SA_PV_ERR_RECOVERABLE_RETURN_IF((key_h_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid key_h_out");
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion fota/bspatch/bspatch_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#define INCLUDE_BSPATCH_PRIVATE_H_

#include "bspatch.h"
#include "common.h"
#include "bspatch_common.h"

/* Patch applied successfully, but new file is not ready yet. User should re-fill patch buffer and call bspatch again. */
#define BSPATCH_NEED_MORE_PATCH_DATA 1
Expand Down
4 changes: 3 additions & 1 deletion fota/bspatch_fota_mbed.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// in order to avoid collision with the ones used in UC-Hub
// (due to the nature of mbed-os source file globbing)

#if (defined(__MBED__) || defined(__NANOSIMULATOR__)) && defined(MBED_CLOUD_CLIENT_FOTA_ENABLE)
#if !defined(FOTA_UNIT_TEST)
#include "MbedCloudClientConfig.h"
#endif

#if (defined(__MBED__) || defined(__NANOSIMULATOR__)) && defined(MBED_CLOUD_CLIENT_FOTA_ENABLE)
#include "bspatch/bspatch.c"
#include "bspatch/lz4.c"
#include "bspatch/varint.c"
Expand Down
Loading

0 comments on commit d7edc52

Please sign in to comment.