diff --git a/applications/asset_tracker_v2/overlay-carrier.conf b/applications/asset_tracker_v2/overlay-carrier.conf index b5ce5b215f9e..025cd469f818 100644 --- a/applications/asset_tracker_v2/overlay-carrier.conf +++ b/applications/asset_tracker_v2/overlay-carrier.conf @@ -30,3 +30,6 @@ CONFIG_MPU_ALLOW_FLASH_WRITE=y # Default partition for NVS is unused CONFIG_PM_PARTITION_SIZE_NVS_STORAGE=0 + +# DFU target library +CONFIG_DFU_TARGET=y diff --git a/applications/asset_tracker_v2/src/modules/cloud_module.c b/applications/asset_tracker_v2/src/modules/cloud_module.c index 6d5da13e8e75..a24952882a64 100644 --- a/applications/asset_tracker_v2/src/modules/cloud_module.c +++ b/applications/asset_tracker_v2/src/modules/cloud_module.c @@ -855,12 +855,14 @@ static int setup(void) return err; } -#if defined(CONFIG_MCUBOOT_IMG_MANAGER) +#if (defined(CONFIG_MCUBOOT_IMG_MANAGER) && !defined(CONFIG_LWM2M_CARRIER)) /* After a successful initializaton, tell the bootloader that the * current image is confirmed to be working. + * If the LwM2M Carrier library is enabled, allow the library to confirm + * the image. */ boot_write_img_confirmed(); -#endif /* CONFIG_MCUBOOT_IMG_MANAGER */ +#endif /* CONFIG_MCUBOOT_IMG_MANAGER && !CONFIG_LWM2M_CARRIER */ return 0; } diff --git a/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst b/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst index b566bf712fa7..c457b62c625d 100644 --- a/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst +++ b/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst @@ -79,7 +79,7 @@ Syntax The ```` command is a string, and can be used as follows: -* ``AT#XCARRIER="app_data"[,][,,]`` +* ``AT#XCARRIER="app_data_set"[,][,,]`` Put the value in ```` into the indicated path. ```` must be an opaque string in double quotes, unless ``slm_data_mode`` is enabled. @@ -174,6 +174,12 @@ The ```` command is a string, and can be used as follows: Request to reboot the device. +* ``AT#XCARRIER="send",,,[,]`` + + Perform a Send operation to send the currently stored data in the indicated resource or resource instance to the server. + This operation is currently only supported for readable opaque resources. + The URI path of the resource or resource instance is indicated as ``////``. + * ``AT#XCARRIER="time"`` Read the time reported by the device, including the UTC time, the UTC offset and the timezone. @@ -268,6 +274,11 @@ Examples AT#XCARRIER="position","63.43","10.47","48",1708684683,"30.5" OK +:: + + AT#XCARRIER="send",19,0,0,0 + OK + Read command ------------ @@ -339,6 +350,13 @@ The ```` command is a string, and can be used as follows: Two special values may also be used: ``-1`` to always use Confirmable notifications, or ``0`` to use the default interval of 86400 seconds. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_COAP_CON_INTERVAL` Kconfig option. +* ``AT#XCARRIERCFG="download_timeout"[,]`` + + Configure the time allowed for a single firmware image download before it is aborted. + This configuration is only supported for Push delivery method of firmware images. + ```` must be an integer value specified in minutes. + For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT` Kconfig option. + * ``AT#XCARRIERCFG="config_enable"[,<0|1>]`` Set flag to apply the stored settings to the general Kconfig options (see the :ref:`general_options_lwm2m` section of the library's documentation). @@ -407,6 +425,13 @@ The ```` command is a string, and can be used as follows: For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_PDN_TYPE` Kconfig option. +* ``AT#XCARRIERCFG="queue_mode"[,<0|1>]`` + + Configure whether the LwM2M carrier library is to inform the server that it may be disconnected for an extended period of time. + This configuration corresponds to the Queue Mode Operation as defined in the OMA LwM2M specification. + This command accepts two possible input parameters: ``0`` to disable or ``1`` to enable. + For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_QUEUE_MODE` Kconfig option. + * ``AT#XCARRIERCFG="binding"[,]`` Configure the binding over which the LwM2M carrier library is to connect to the device management network. diff --git a/applications/serial_lte_modem/doc/slm_data_mode.rst b/applications/serial_lte_modem/doc/slm_data_mode.rst index ba20d22c06e3..a0503ef38a53 100644 --- a/applications/serial_lte_modem/doc/slm_data_mode.rst +++ b/applications/serial_lte_modem/doc/slm_data_mode.rst @@ -51,7 +51,7 @@ Other examples: * ``AT#XFTP="mput",`` * ``AT#XMQTTPUB=,"",,`` * ``AT#XNRFCLOUD=2`` -* ``AT#XCARRIER="app_data"`` +* ``AT#XCARRIER="app_data_set"`` The SLM application sends an *OK* response when it successfully enters data mode. diff --git a/applications/serial_lte_modem/overlay-carrier.conf b/applications/serial_lte_modem/overlay-carrier.conf index 5a38ff0c1d56..c0f1e53d429d 100644 --- a/applications/serial_lte_modem/overlay-carrier.conf +++ b/applications/serial_lte_modem/overlay-carrier.conf @@ -25,3 +25,6 @@ CONFIG_SLM_CUSTOMER_VERSION="lwm2m_carrier" # Enable LwM2M carrier settings support CONFIG_LWM2M_CARRIER_SETTINGS=y + +# DFU target library +CONFIG_DFU_TARGET=y diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig b/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig index b2277a33c074..7f81b01538ce 100644 --- a/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig +++ b/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig @@ -11,11 +11,10 @@ config SLM_CARRIER if SLM_CARRIER config SLM_CARRIER_APP_DATA_BUFFER_LEN - int "Size of the buffer for sending application data" + int "Size of the buffer for setting application data" default 512 help - Specifies maximum application data size to be sent to the server - through the App Data Container, the Binary App Data Container or - the Event Log objects. + Specifies maximum application data size to be set in the App Data Container, + the Binary App Data Container or the Event Log objects. endif # SLM_CARRIER diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c index 268d4a23c629..20ed35419522 100644 --- a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c +++ b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c @@ -20,7 +20,7 @@ LOG_MODULE_REGISTER(slm_carrier, CONFIG_SLM_LOG_LEVEL); /**@brief LwM2M Carrier operations. */ enum slm_carrier_operation { /* Carrier AppData Operation */ - CARRIER_OP_APPDATA_SEND, + CARRIER_OP_APPDATA_SET, /* Carrier Device Operation */ CARRIER_OP_DEVICE_BATTERY_LEVEL, CARRIER_OP_DEVICE_BATTERY_STATUS, @@ -45,6 +45,8 @@ enum slm_carrier_operation { CARRIER_OP_REQUEST_REBOOT, CARRIER_OP_REQUEST_LINK_DOWN, CARRIER_OP_REQUEST_LINK_UP, + /* Carrier Send Operation */ + CARRIER_OP_SEND, /* Count */ CARRIER_OP_MAX }; @@ -59,7 +61,7 @@ struct carrier_op_list { static int m_mem_free; /** forward declaration of cmd handlers **/ -static int do_carrier_appdata_send(void); +static int do_carrier_appdata_set(void); static int do_carrier_device_battery_level(void); static int do_carrier_device_battery_status(void); static int do_carrier_device_current(void); @@ -79,10 +81,11 @@ static int do_carrier_portfolio(void); static int do_carrier_request_reboot(void); static int do_carrier_request_link_down(void); static int do_carrier_request_link_up(void); +static int do_carrier_send(void); /**@brief SLM Carrier AT Command list type. */ static struct carrier_op_list op_list[CARRIER_OP_MAX] = { - {CARRIER_OP_APPDATA_SEND, "app_data", do_carrier_appdata_send}, + {CARRIER_OP_APPDATA_SET, "app_data_set", do_carrier_appdata_set}, {CARRIER_OP_DEVICE_BATTERY_LEVEL, "battery_level", do_carrier_device_battery_level}, {CARRIER_OP_DEVICE_BATTERY_STATUS, "battery_status", do_carrier_device_battery_status}, {CARRIER_OP_DEVICE_CURRENT, "current", do_carrier_device_current}, @@ -102,6 +105,7 @@ static struct carrier_op_list op_list[CARRIER_OP_MAX] = { {CARRIER_OP_REQUEST_REBOOT, "reboot", do_carrier_request_reboot}, {CARRIER_OP_REQUEST_LINK_DOWN, "link_down", do_carrier_request_link_down}, {CARRIER_OP_REQUEST_LINK_UP, "link_up", do_carrier_request_link_up}, + {CARRIER_OP_SEND, "send", do_carrier_send}, }; #define SLM_CARRIER_OP_STR_MAX (sizeof("battery_status") + 1) @@ -276,7 +280,7 @@ int lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *event) return err; } -/* Carrier App Data Send data mode handler */ +/* Carrier App Data Set data mode handler */ static int carrier_datamode_callback(uint8_t op, const uint8_t *data, int len, uint8_t flags) { int ret = 0; @@ -290,7 +294,7 @@ static int carrier_datamode_callback(uint8_t op, const uint8_t *data, int len, u uint16_t path[3] = { LWM2M_CARRIER_OBJECT_APP_DATA_CONTAINER, 0, 0 }; uint8_t path_len = 3; - ret = lwm2m_carrier_app_data_send(path, path_len, data, len); + ret = lwm2m_carrier_app_data_set(path, path_len, data, len); LOG_INF("datamode send: %d", ret); if (ret < 0) { (void)exit_datamode_handler(ret); @@ -302,8 +306,8 @@ static int carrier_datamode_callback(uint8_t op, const uint8_t *data, int len, u return ret; } -/* AT#XCARRIER="app_data"[,][,,] */ -static int do_carrier_appdata_send(void) +/* AT#XCARRIER="app_data_set"[,][,,] */ +static int do_carrier_appdata_set(void) { int ret = 0; @@ -327,7 +331,7 @@ static int do_carrier_appdata_send(void) return ret; } - ret = lwm2m_carrier_app_data_send(path, path_len, data, size); + ret = lwm2m_carrier_app_data_set(path, path_len, data, size); } else if (param_count == 4 || param_count == 5) { uint8_t *data = NULL; char buffer[CONFIG_SLM_CARRIER_APP_DATA_BUFFER_LEN] = {0}; @@ -362,7 +366,7 @@ static int do_carrier_appdata_send(void) data = buffer; } - ret = lwm2m_carrier_app_data_send(path, path_len, data, size); + ret = lwm2m_carrier_app_data_set(path, path_len, data, size); } return ret; @@ -853,6 +857,33 @@ static int do_carrier_request_link_up(void) return lwm2m_carrier_request(LWM2M_CARRIER_REQUEST_LINK_UP); } +/* AT#XCARRIER="send",,,[,] */ +static int do_carrier_send(void) +{ + int ret = 0; + + uint32_t param_count = at_params_valid_count_get(&slm_at_param_list); + + if (param_count != 5 && param_count != 6) { + LOG_DBG("AT#XCARRIER=\"send\" failed: invalid number of arguments"); + return -EINVAL; + } + + uint16_t path[4]; + uint8_t path_len = 0; + + for (int i = 2; i < param_count; i++) { + ret = at_params_unsigned_short_get(&slm_at_param_list, i, &path[i - 2]); + if (ret) { + return ret; + } + + ++path_len; + } + + return lwm2m_carrier_data_send(path, path_len); +} + /** * @brief API to handle AT#XCARRIER command. */ diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c index 09ffe3b6f607..e5277504130b 100644 --- a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c +++ b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c @@ -24,9 +24,11 @@ enum slm_carrier_cfg_operation { CARRIER_CFG_OP_CONFIG_BOOTSTRAP_FROM_SMARTCARD, CARRIER_CFG_OP_CONFIG_CARRIERS, CARRIER_CFG_OP_CONFIG_COAP_CON_INTERVAL, + CARRIER_CFG_OP_CONFIG_FIRMWARE_DOWNLOAD_TIMEOUT, CARRIER_CFG_OP_CONFIG_LGU_DEVICE_SERIAL_NO_TYPE, CARRIER_CFG_OP_CONFIG_LGU_SERVICE_CODE, CARRIER_CFG_OP_CONFIG_PDN_TYPE, + CARRIER_CFG_OP_CONFIG_QUEUE_MODE, CARRIER_CFG_OP_CONFIG_SESSION_IDLE_TIMEOUT, /* Device Custom Configuration */ CARRIER_CFG_OP_DEVICE_ENABLE, @@ -52,6 +54,7 @@ static int do_cfg_auto_startup(void); static int do_cfg_bootstrap_from_smartcard(void); static int do_cfg_carriers(void); static int do_cfg_coap_con_interval(void); +static int do_cfg_firmware_download_timeout(void); static int do_cfg_config_enable(void); static int do_cfg_device_enable(void); static int do_cfg_device_type(void); @@ -63,6 +66,7 @@ static int do_cfg_software_version(void); static int do_cfg_device_serial_no_type(void); static int do_cfg_service_code(void); static int do_cfg_pdn_type(void); +static int do_cfg_queue_mode(void); static int do_cfg_binding(void); static int do_cfg_server_enable(void); static int do_cfg_is_bootstrap(void); @@ -84,11 +88,14 @@ static struct carrier_cfg_op_list cfg_op_list[CARRIER_CFG_OP_MAX] = { do_cfg_bootstrap_from_smartcard}, {CARRIER_CFG_OP_CONFIG_CARRIERS, "carriers", do_cfg_carriers}, {CARRIER_CFG_OP_CONFIG_COAP_CON_INTERVAL, "coap_con_interval", do_cfg_coap_con_interval}, + {CARRIER_CFG_OP_CONFIG_FIRMWARE_DOWNLOAD_TIMEOUT, "download_timeout", + do_cfg_firmware_download_timeout}, {CARRIER_CFG_OP_CONFIG_ENABLE, "config_enable", do_cfg_config_enable}, {CARRIER_CFG_OP_CONFIG_LGU_DEVICE_SERIAL_NO_TYPE, "device_serial_no_type", do_cfg_device_serial_no_type}, {CARRIER_CFG_OP_CONFIG_LGU_SERVICE_CODE, "service_code", do_cfg_service_code}, {CARRIER_CFG_OP_CONFIG_PDN_TYPE, "pdn_type", do_cfg_pdn_type}, + {CARRIER_CFG_OP_CONFIG_QUEUE_MODE, "queue_mode", do_cfg_queue_mode}, {CARRIER_CFG_OP_CONFIG_SESSION_IDLE_TIMEOUT, "session_idle_timeout", do_cfg_session_idle_timeout}, {CARRIER_CFG_OP_DEVICE_ENABLE, "device_enable", do_cfg_device_enable}, @@ -221,7 +228,7 @@ static int do_cfg_bootstrap_from_smartcard(void) const static uint32_t carriers_enabled_map[] = { LWM2M_CARRIER_GENERIC, LWM2M_CARRIER_VERIZON, - LWM2M_CARRIER_ATT, + LWM2M_CARRIER_BELL_CA, LWM2M_CARRIER_LG_UPLUS, LWM2M_CARRIER_T_MOBILE, LWM2M_CARRIER_SOFTBANK @@ -316,6 +323,31 @@ static int do_cfg_coap_con_interval(void) return lwm2m_settings_coap_con_interval_set(coap_con_interval); } +/* AT#XCARRIERCFG="download_timeout"[,] */ +static int do_cfg_firmware_download_timeout(void) +{ + uint32_t count; + + count = at_params_valid_count_get(&slm_at_param_list); + if (count == 2) { + rsp_send("\r\n#XCARRIERCFG: %hu\r\n", + lwm2m_settings_firmware_download_timeout_get()); + return 0; + } else if (count != 3) { + return -EINVAL; + } + + int ret; + uint16_t firmware_download_timeout; + + ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &firmware_download_timeout); + if (ret) { + return ret; + } + + return lwm2m_settings_firmware_download_timeout_set(firmware_download_timeout); +} + /* AT#XCARRIERCFG="config_enable"[,<0|1>] */ static int do_cfg_config_enable(void) { @@ -631,6 +663,35 @@ static int do_cfg_pdn_type(void) return lwm2m_settings_pdn_type_set(pdn_type); } +/* AT#XCARRIERCFG="queue_mode"[,<0|1>] */ +static int do_cfg_queue_mode(void) +{ + uint32_t count; + + count = at_params_valid_count_get(&slm_at_param_list); + if (count == 2) { + rsp_send("\r\n#XCARRIERCFG: %d\r\n", lwm2m_settings_queue_mode_get()); + return 0; + } else if (count != 3) { + return -EINVAL; + } + + int ret; + uint16_t queue_mode; + + ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &queue_mode); + if (ret) { + return ret; + } + + if (queue_mode > 1) { + LOG_ERR("AT#XCARRIERCFG=\"queue_mode\" failed: must be 0 or 1"); + return -EINVAL; + } + + return lwm2m_settings_queue_mode_set(queue_mode); +} + /* AT#XCARRIERCFG="binding"[,] */ static int do_cfg_binding(void) { diff --git a/applications/serial_lte_modem/src/main.c b/applications/serial_lte_modem/src/main.c index 3021fa67df7e..3195c230f2ce 100644 --- a/applications/serial_lte_modem/src/main.c +++ b/applications/serial_lte_modem/src/main.c @@ -423,6 +423,25 @@ static void check_app_fota_status(void) slm_fota_stage = FOTA_STAGE_COMPLETE; } +#if defined(CONFIG_LWM2M_CARRIER) +static atomic_t app_fota_status_checked; + +bool lwm2m_os_dfu_application_update_validate(void) +{ + if (atomic_cas(&app_fota_status_checked, false, true)) { + check_app_fota_status(); + } + + if ((slm_fota_type == DFU_TARGET_IMAGE_TYPE_MCUBOOT) && + (slm_fota_status == FOTA_STATUS_OK) && + (slm_fota_stage == FOTA_STAGE_COMPLETE)) { + return true; + } + + return false; +} +#endif /* CONFIG_LWM2M_CARRIER */ + int lte_auto_connect(void) { int err = 0; @@ -558,7 +577,16 @@ int main(void) } } +#if defined(CONFIG_LWM2M_CARRIER) + /* If LwM2M Carrier library is enabled, the library might have already validated the + * running application image; this should only be performed once. + */ + if (atomic_cas(&app_fota_status_checked, false, true)) { + check_app_fota_status(); + } +#else check_app_fota_status(); +#endif /* CONFIG_LWM2M_CARRIER */ #if defined(CONFIG_SLM_START_SLEEP) diff --git a/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst b/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst index 1161d08ab1df..01721394e288 100644 --- a/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst +++ b/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst @@ -9,30 +9,71 @@ Changelog All notable changes to this project are documented in this file. -liblwm2m_carrier 3.3.3 +Certification status +==================== + +For certification status of the released versions, see `Mobile network operator certifications`_. + +liblwm2m_carrier 3.4.0 ********************** -Release for modem firmware version 1.3.5 and 2.0.0. +Release for modem firmware version 1.3.5, 1.3.6, 2.0.0, and 2.0.1. -Certification status -==================== +Size +==== + +See :ref:`lwm2m_lib_size` for an explanation of the library size in different scenarios. -For certification status, see `Mobile network operator certifications`_. ++-------------------------+---------------+------------+ +| | Flash (Bytes) | RAM (Bytes)| ++-------------------------+---------------+------------+ +| Library size | 77020 | 19435 | +| (binary) | | | ++-------------------------+---------------+------------+ +| Library size | 97252 | 34088 | +| (reference application) | | | ++-------------------------+---------------+------------+ Changes ======= -* Minor fixes and improvements. +* Removed AT&T support. + The LwM2M carrier library is no longer required to certify with AT&T. -liblwm2m_carrier 3.3.2 +* Added preliminary support for Bell Canada subscriber ID. + This carrier can be disabled or enabled with the Kconfig option :kconfig:option:`CONFIG_LWM2M_CARRIER_BELL_CA`. + +* Changed the default string of the Device Type resource to say "Module" instead of "Smart Device". + This can be changed to other strings using the Kconfig option :kconfig:option:`CONFIG_LWM2M_CARRIER_DEVICE_TYPE`. + +* Added ``disable_queue_mode`` to the configuration :c:macro:`lwm2m_carrier_config_t`. + Queue Mode can now be disabled using the Kconfig option :kconfig:option:`CONFIG_LWM2M_CARRIER_QUEUE_MODE`. + +* Added a timeout to abort Push FOTA operations using the :kconfig:option:`CONFIG_LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT` Kconfig option. + By default (0), the timer is disabled for unknown subscriber IDs, and set to 30 minutes for the SoftBank subscriber ID. + +* Removed the Kconfig option ``LWM2M_CARRIER_THREAD_STACK_SIZE``, and the corresponding thread from the glue layer. + +* Added the function :c:func:`lwm2m_carrier_data_send`. + This function can be used to send Binary App Data Container and Event Log object data. + + * Renamed the old ``lwm2m_carrier_app_data_send`` function to :c:func:`lwm2m_carrier_app_data_set` to avoid confusion with the new :c:func:`lwm2m_carrier_data_send` function. + The name now also matches the similar function :c:func:`lwm2m_carrier_log_data_set`. + +liblwm2m_carrier 3.3.3 ********************** Release for modem firmware version 1.3.5 and 2.0.0. -Certification status -==================== +Changes +======= + +* Minor fixes and improvements. -For certification status, see `Mobile network operator certifications`_. +liblwm2m_carrier 3.3.2 +********************** + +Release for modem firmware version 1.3.5 and 2.0.0. Changes ======= @@ -45,11 +86,6 @@ liblwm2m_carrier 3.3.1 Release for modem firmware version 1.3.5 and 2.0.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -60,11 +96,6 @@ liblwm2m_carrier 3.3.0 Release for modem firmware version 1.3.5 and 2.0.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -94,7 +125,7 @@ Changes * New successful event flow: :c:member:`LWM2M_CARRIER_EVENT_FOTA_START` > :c:member:`LWM2M_CARRIER_EVENT_LTE_POWER_OFF` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_SHUTDOWN` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_INIT` > :c:member:`LWM2M_CARRIER_EVENT_FOTA_SUCCESS` > :c:member:`LWM2M_CARRIER_EVENT_LTE_LINK_UP`. AT&T support has been deprecated --------------------------------- +================================ The application must no longer connect to the AT&T Device Management server. Consequently, the LwM2M carrier library is no longer required to certify with AT&T. @@ -110,11 +141,6 @@ liblwm2m_carrier 3.2.0 Release for modem firmware version 1.3.5. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -155,7 +181,7 @@ Changes * New successful event flow: :c:member:`LWM2M_CARRIER_EVENT_FOTA_START` > :c:member:`LWM2M_CARRIER_EVENT_LTE_POWER_OFF` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_SHUTDOWN` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_INIT` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_INIT` > :c:member:`LWM2M_CARRIER_EVENT_FOTA_SUCCESS` > :c:member:`LWM2M_CARRIER_EVENT_LTE_LINK_UP`. nRF modem dependency change ---------------------------- +=========================== LwM2M carrier library no longer explicitly controls the :ref:`nrf_modem`. Instead, the application can initialize the Modem library at its own convenience. @@ -187,11 +213,6 @@ liblwm2m_carrier 3.1.0 Release for modem firmware version 1.3.3 and 1.3.4. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -306,11 +327,6 @@ liblwm2m_carrier 0.30.2 Release for modem firmware version 1.3.3. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -338,11 +354,6 @@ liblwm2m_carrier 0.30.1 Release for modem firmware version 1.3.3. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -353,11 +364,6 @@ liblwm2m_carrier 0.30.0 Release for modem firmware version 1.3.1 and 1.3.2. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -438,11 +444,6 @@ liblwm2m_carrier 0.22.0 Release for modem firmware version 1.3.1. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -475,11 +476,6 @@ liblwm2m_carrier 0.21.0 Release for modem firmware version 1.3.1. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -519,11 +515,6 @@ liblwm2m_carrier 0.20.1 Release for modem firmware version 1.3.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -549,11 +540,6 @@ liblwm2m_carrier 0.20.0 Release for modem firmware version 1.3.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -572,11 +558,6 @@ liblwm2m_carrier 0.10.2 Release for modem firmware versions 1.2.3 and 1.1.4, and |NCS| 1.4.2. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -603,11 +584,6 @@ liblwm2m_carrier 0.10.1 Release for modem firmware versions 1.2.2 and 1.1.4, and |NCS| 1.4.1. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -624,11 +600,6 @@ Modem firmware version 1.1.4 must be used for Verizon, and the modem firmware ve The snapshot can be used for development and testing only. It is not ready for certification. -Certification status -==================== - -The library is not certified with any carrier. - Changes ======= @@ -643,11 +614,6 @@ liblwm2m_carrier 0.9.1 Release with AT&T support, intended for modem firmware version 1.2.1 and |NCS| version 1.3.1. -Certification status -==================== - -The library is certified with AT&T. - Size ==== @@ -677,11 +643,6 @@ This release is intended to let users begin integration towards the AT&T and Ver It can be used for development and testing only. It is not ready for certification. -Certification status -==================== - -The library is not certified with any carrier. - Changes ======= @@ -704,11 +665,6 @@ liblwm2m_carrier 0.8.2 Release for modem firmware version 1.1.2, with support for Verizon Wireless. -Certification status -==================== - -The library is certified with Verizon Wireless. - Changes ======= @@ -736,11 +692,6 @@ liblwm2m_carrier 0.8.1+build1 Release for modem firmware version 1.1.0, with support for Verizon Wireless. -Certification status -==================== - -The library is certified with Verizon Wireless. - Changes ======= @@ -766,11 +717,6 @@ liblwm2m_carrier 0.8.1 Release for modem firmware version 1.1.0, with support for Verizon Wireless. -Certification status -==================== - -The library is certified with Verizon Wireless. - Changes ======= @@ -796,11 +742,6 @@ liblwm2m_carrier 0.8.0 Release for modem firmware version 1.1.0 and |NCS| v1.1.0, with support for Verizon Wireless. -Certification status -==================== - -The library is not certified with Verizon Wireless. - Changes ======= @@ -820,7 +761,7 @@ Changes The application must set and maintain these values to reflect the state of the device. Updated values are pushed to the servers autonomously. -* Added API to set the "Device Type" resource. If not set, this is reported as "Smart Device". +* Added API to set the ``Device Type`` resource. If not set, this is reported as ``Smart Device``. * Added API to set the "Software Version" resource. If not set, this is reported as "LwM2M 0.8.0". * Added API to set the "Hardware Version" resource. If not set, this is reported as "1.0". diff --git a/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst b/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst index f29693cae575..54d8ca4edeb5 100644 --- a/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst +++ b/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst @@ -104,7 +104,7 @@ Following are some of the general Kconfig options that you can configure: * The default value is ``IPV4V6``. * If :kconfig:option:`CONFIG_LWM2M_CARRIER_CUSTOM_APN` is not set, this configuration is ignored. -* :kconfig:option:`CONFIG_LWM2M_CARRIER_GENERIC`, :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON`, :kconfig:option:`CONFIG_LWM2M_CARRIER_ATT`, :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS`, :kconfig:option:`CONFIG_LWM2M_CARRIER_T_MOBILE`, :kconfig:option:`CONFIG_LWM2M_CARRIER_SOFTBANK`: +* :kconfig:option:`CONFIG_LWM2M_CARRIER_GENERIC`, :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON`, :kconfig:option:`CONFIG_LWM2M_CARRIER_BELL_CA`, :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS`, :kconfig:option:`CONFIG_LWM2M_CARRIER_T_MOBILE`, :kconfig:option:`CONFIG_LWM2M_CARRIER_SOFTBANK`: * These configurations allow you to choose the networks in which the carrier library will apply. * For example, if you are deploying a product in several networks but only need to enable the carrier library within Verizon, you must set :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON` to ``y`` and all the others to ``n``. @@ -123,6 +123,13 @@ Following are some of the general Kconfig options that you can configure: .. note:: Application DFU is needed to enable LG U+ functionality. +* :kconfig:option:`CONFIG_LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT`: + + * This configuration specifies the time (in minutes) allowed for a single firmware image download. + * If the download is not completed by the time the specified number of minutes elapses, the download shall be aborted. + * This configuration is only supported for Push delivery method of firmware images. + * Leaving this configuration empty (``0``) disables the timer for unknown subscriber IDs, and set it to 30 minutes for the SoftBank subscriber ID. + .. _server_options_lwm2m: Server options diff --git a/lib/bin/lwm2m_carrier/Kconfig b/lib/bin/lwm2m_carrier/Kconfig index 87158d06e04d..504b7b38e219 100644 --- a/lib/bin/lwm2m_carrier/Kconfig +++ b/lib/bin/lwm2m_carrier/Kconfig @@ -34,6 +34,8 @@ menuconfig LWM2M_CARRIER depends on (AT_MONITOR_HEAP_SIZE >= 320) # reboot functionality depends on REBOOT + # Firmware upgrade functionality + depends on DFU_TARGET help A library for cellular connection management. @@ -54,12 +56,6 @@ config LWM2M_CARRIER_VERIZON help Enable Carrier Library when the SIM Subscriber ID is Verizon. -config LWM2M_CARRIER_ATT - bool "AT&T" - default n - help - Enable Carrier Library when the SIM Subscriber ID is AT&T. - config LWM2M_CARRIER_LG_UPLUS bool "LG U+" depends on DFU_TARGET_MCUBOOT @@ -105,6 +101,12 @@ config LWM2M_CARRIER_SOFTBANK help Enable Carrier Library when the SIM Subscriber ID is SoftBank. +config LWM2M_CARRIER_BELL_CA + bool "Bell Canada" + default y + help + Enable Carrier Library when the SIM Subscriber ID is Bell Canada. + endmenu config LWM2M_CARRIER_CUSTOM_URI @@ -195,6 +197,13 @@ config LWM2M_CARRIER_BOOTSTRAP_SMARTCARD help Bootstrap from Smartcard mode when this is enabled by the carrier. +config LWM2M_CARRIER_QUEUE_MODE + bool "Enable queue mode" + default y + help + Configure whether the LwM2M device is to inform the LwM2M server that + it may be disconnected for an extended period of time. + config LWM2M_CARRIER_DEVICE_MANUFACTURER string "Device manufacturer" default "" @@ -213,7 +222,7 @@ config LWM2M_CARRIER_DEVICE_MODEL_NUMBER config LWM2M_CARRIER_DEVICE_TYPE string "Device type" - default "Smart Device" + default "Module" help Set the LwM2M device type (manufacturer-specified string). Some carriers may override this value. @@ -250,17 +259,29 @@ config LWM2M_CARRIER_COAP_CON_INTERVAL Setting this to 0 will use the default value (86400s). Setting this to -1 will always use Confirmable notifications. +config LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT + int "Firmware download timeout" + range 0 65535 + default 0 + help + Number of minutes allowed for a single firmware image download. + If the download is not completed by the time the specified number of minutes elapses, + the download shall be aborted. This configuration is currently only supported for + PUSH delivery method of firmware images. + Setting this to 0 will disable the use of this timer. + config LWM2M_CARRIER_WORKQ_STACK_SIZE int "LwM2M carrier work queue stack size" - default 4096 + default 2048 if NEWLIB_LIBC + default 1536 help - Stack size for the LwM2M work queue thread. + Stack size for the LwM2M carrier client work queue threads. config LWM2M_CARRIER_THREAD_STACK_SIZE int "LwM2M carrier thread stack size" - default 600 + default 1536 help - Stack size for the LwM2M carrier process thread. + Stack size for the LwM2M carrier thread. config LWM2M_CARRIER_STORAGE_AREA_SIZE hex "Size of the lwm2m_carrier partition" @@ -284,7 +305,6 @@ config LWM2M_CARRIER_SHELL bool "LwM2M carrier shell" depends on SHELL depends on LWM2M_CARRIER_SETTINGS - depends on MODEM_KEY_MGMT help Include LwM2M carrier shell diff --git a/lib/bin/lwm2m_carrier/include/lwm2m_carrier.h b/lib/bin/lwm2m_carrier/include/lwm2m_carrier.h index d196a6add346..6fefbc7c944a 100644 --- a/lib/bin/lwm2m_carrier/include/lwm2m_carrier.h +++ b/lib/bin/lwm2m_carrier/include/lwm2m_carrier.h @@ -59,22 +59,10 @@ extern "C" { #define LWM2M_CARRIER_EVENT_ERROR 20 /** @} */ -/** - * @name LwM2M carrier library firmware update types. - * @{ - */ -/** Receiving a modem firmware delta patch. */ -#define LWM2M_CARRIER_FOTA_START_MODEM_DELTA 0 -/** Receiving application firmware. */ -#define LWM2M_CARRIER_FOTA_START_APPLICATION 2 -/** @} */ - /** * @brief LwM2M carrier library firmware update event structure. */ typedef struct { - /** Firmware type to be received. */ - uint32_t type; /** URI from where the firmware will be downloaded. Set to NULL if no URI will be used. */ const char *uri; } lwm2m_carrier_event_fota_start_t; @@ -329,22 +317,24 @@ typedef struct { */ #define LWM2M_CARRIER_GENERIC 0x00000001 #define LWM2M_CARRIER_VERIZON 0x00000002 -#define LWM2M_CARRIER_ATT 0x00000004 /* AT&T specific support is deprecated. */ #define LWM2M_CARRIER_LG_UPLUS 0x00000008 #define LWM2M_CARRIER_T_MOBILE 0x00000010 #define LWM2M_CARRIER_SOFTBANK 0x00000020 +#define LWM2M_CARRIER_BELL_CA 0x00000040 /** @} */ /** * @brief Structure holding LwM2M carrier library initialization parameters. */ typedef struct { - /** Configure enabled carriers. All carriers except AT&T are enabled when no bits are set + /** Configure enabled carriers. All carriers are enabled when no bits are set * or if all bits are set. */ uint32_t carriers_enabled; /** Disable bootstrap from Smartcard mode when this is enabled by the carrier. */ bool disable_bootstrap_from_smartcard; + /** Disable queue mode. */ + bool disable_queue_mode; /** Denotes whether @c server_uri is an LwM2M Bootstrap-Server or an LwM2M Server. */ bool is_bootstrap_server; /** Optional URI of the custom server. Null-terminated string of max 255 characters. */ @@ -359,6 +349,8 @@ typedef struct { int32_t session_idle_timeout; /** How often to send CON instead of NON in CoAP observables (in seconds). */ int32_t coap_con_interval; + /** Optional firmware download timeout (in minutes). Only applicable to PUSH delivery. */ + uint16_t firmware_download_timeout; /** Optional custom APN. Null-terminated string of max 63 characters. */ const char *apn; /** Optional PDN type for custom APN. */ @@ -746,8 +738,8 @@ int lwm2m_carrier_velocity_set(int heading, float speed_h, float speed_v, float float uncertainty_v); /** - * @brief Schedule application data to be set using either the Binary App Data Container object - * or the App Data Container object. + * @brief Set application data in either the Binary App Data Container object or the App Data + * Container object. * * @details This function sets the resource given by the path to the desired value. The resource * can then be read by, or reported to, the LwM2M server. @@ -755,12 +747,12 @@ int lwm2m_carrier_velocity_set(int heading, float speed_h, float speed_v, float * @note Both the Binary App Data Container object and the App Data Container object will not be * initialized for every carrier. * - * @param[in] path The path of the resource or resource instance to be sent to. The path + * @param[in] path The path of the resource or resource instance which is to be set. The path * contains the object id, object instance id, resource id and resource * instance id in order. The resource instance id is not needed for the * App Data Container object. * @param[in] path_len The length of the path. Must be 3 or 4. - * @param[in] buffer Buffer containing the application data to be sent. If this is set to null + * @param[in] buffer Buffer containing the application data to be set. If this is set to null * the resource instance is deleted instead when using the Binary App Data * Container object. * @param[in] buffer_len Number of bytes in the buffer. @@ -770,11 +762,28 @@ int lwm2m_carrier_velocity_set(int heading, float speed_h, float speed_v, float * @retval -EINVAL If at least one input argument is incorrect. * @retval -ENOMEM If there is not enough memory to copy the buffer contents to the resource model. */ -int lwm2m_carrier_app_data_send(const uint16_t *path, uint16_t path_len, const uint8_t *buffer, - size_t buffer_len); +int lwm2m_carrier_app_data_set(const uint16_t *path, uint16_t path_len, const uint8_t *buffer, + size_t buffer_len); + +/** + * @brief Schedule data to be sent to a LwM2M Server. + * + * @note This is only supported for some resources, which may not be initialized for every carrier. + * + * @param[in] path The path of the resource or resource instance to be sent. The path contains + * the object id, object instance id, resource id and resource instance id in + * order. + * @param[in] path_len The length of the path. Must be 3 or 4. + * + * @retval 0 If the data has been sent successfully. + * @retval -ENOENT If the path points to something that is not yet initialized. + * @retval -EINVAL If the operation was attempted on an unsupported resource. + * @retval -EINPROGRESS If the operation was attempted while a send request was already in progress. + */ +int lwm2m_carrier_data_send(const uint16_t *path, uint8_t path_len); /** - * @brief Send log data using the Event Log object. + * @brief Set log data in the Event Log object. * * @note The Event Log object will not be initialized for every carrier. * diff --git a/lib/bin/lwm2m_carrier/include/lwm2m_os.h b/lib/bin/lwm2m_carrier/include/lwm2m_os.h index 3a2698058aee..d6bb8ab9b5fb 100644 --- a/lib/bin/lwm2m_carrier/include/lwm2m_os.h +++ b/lib/bin/lwm2m_carrier/include/lwm2m_os.h @@ -30,22 +30,15 @@ extern "C" { /** * @brief Maximum number of timers that the system must support. */ -#define LWM2M_OS_MAX_TIMER_COUNT (5 + (LWM2M_OS_MAX_WORK_QS * 4)) +#define LWM2M_OS_MAX_TIMER_COUNT (4 + (LWM2M_OS_MAX_WORK_QS * 4)) typedef int lwm2m_os_work_q_t; typedef int lwm2m_os_timer_t; -/** - * @brief Maximum number of threads that the system must support. - */ -#define LWM2M_OS_MAX_THREAD_COUNT 1 - -typedef void (*lwm2m_os_thread_entry_t)(void *p1, void *p2, void *p3); - /** * @brief Maximum number of semaphores that the system must support. */ -#define LWM2M_OS_MAX_SEM_COUNT (4 + (LWM2M_OS_MAX_WORK_QS * 2)) +#define LWM2M_OS_MAX_SEM_COUNT (6 + (LWM2M_OS_MAX_WORK_QS * 2)) typedef int lwm2m_os_sem_t; @@ -133,6 +126,14 @@ struct lwm2m_os_download_evt { }; }; +/** @brief PDN family */ +enum lwm2m_os_pdn_fam { + LWM2M_OS_PDN_FAM_IPV4, + LWM2M_OS_PDN_FAM_IPV6, + LWM2M_OS_PDN_FAM_IPV4V6, + LWM2M_OS_PDN_FAM_NONIP, +}; + /** * @brief Download client configuration options. */ @@ -143,6 +144,8 @@ struct lwm2m_os_download_cfg { uint8_t sec_tag_count; /** PDN ID to be used for the download. */ int pdn_id; + /** Address family to be used for the download. */ + enum lwm2m_os_pdn_fam family; }; /** @@ -150,14 +153,6 @@ struct lwm2m_os_download_cfg { */ typedef int (*lwm2m_os_download_callback_t)(const struct lwm2m_os_download_evt *event); -/** @brief PDN family */ -enum lwm2m_os_pdn_fam { - LWM2M_OS_PDN_FAM_IPV4, - LWM2M_OS_PDN_FAM_IPV6, - LWM2M_OS_PDN_FAM_IPV4V6, - LWM2M_OS_PDN_FAM_NONIP, -}; - /** @brief PDN event */ enum lwm2m_os_pdn_event { LWM2M_OS_PDN_EVENT_CNEC_ESM, @@ -180,13 +175,6 @@ enum lwm2m_os_pdn_event { typedef void (*lwm2m_os_pdn_event_handler_t) (uint8_t cid, enum lwm2m_os_pdn_event event, int reason); -/** - * @brief Initialize the PDN functionality. - * - * @retval 0 If success. - */ -int lwm2m_os_pdn_init(void); - /** * @brief Create a Packet Data Protocol (PDP) context. * @@ -254,18 +242,6 @@ int lwm2m_os_pdn_deactivate(uint8_t cid); */ int lwm2m_os_pdn_id_get(uint8_t cid); -/** - * @brief Retrieve the default Access Point Name (APN). - * - * The default APN is the APN of the default PDP context (zero). - * - * @param buf The buffer to copy the APN into. - * @param len The size of the output buffer. - * - * @retval 0 If success. - */ -int lwm2m_os_pdn_default_apn_get(char *buf, size_t len); - /** * @brief Set a callback for events pertaining to the default PDP context (zero). * @@ -335,9 +311,7 @@ int64_t lwm2m_os_uptime_delta(int64_t *ref); /** * @brief Put a thread to a sleep. * - * @param ms Desired duration of sleep in milliseconds. Can be -1 for forever, in which case the - * thread is suspended, but can be subsequently resumed by means of - * @ref lwm2m_os_thread_resume. + * @param ms Desired duration of sleep in milliseconds. */ int lwm2m_os_sleep(int ms); @@ -438,25 +412,6 @@ int64_t lwm2m_os_timer_remaining(lwm2m_os_timer_t *timer); */ bool lwm2m_os_timer_is_pending(lwm2m_os_timer_t *timer); -/** - * @brief Create and start a new thread. - * - * @param index Number of the thread. - * @param entry Thread entry function. - * @param name Name of the thread. - * - * @retval 0 Thread created and started. - * @retval -EINVAL Thread index not valid. - */ -int lwm2m_os_thread_start(int index, lwm2m_os_thread_entry_t entry, const char *name); - -/** - * @brief Resume a suspended thread. If the thread is not suspended, this function shall do nothing. - * - * @param index Number of the thread. - */ -void lwm2m_os_thread_resume(int index); - /** * @brief Initialize AT command driver. * @@ -465,16 +420,6 @@ void lwm2m_os_thread_resume(int index); */ int lwm2m_os_at_init(lwm2m_os_at_handler_callback_t callback); -/** - * @brief Initialize SMS subscriber library. - */ -int lwm2m_os_sms_init(void); - -/** - * @brief Uninitialize SMS subscriber library. - */ -void lwm2m_os_sms_uninit(void); - /** * @brief Register as an SMS client/listener. * @@ -546,55 +491,101 @@ void lwm2m_os_lte_mode_request(int32_t prefer); int lwm2m_os_nrf_errno(void); /** - * @brief Start an application firmware upgrade. + * @defgroup lwm2m_os_dfu_img_type LwM2M OS DFU image types. + * @{ + */ +#define LWM2M_OS_DFU_IMG_TYPE_NONE 0 +#define LWM2M_OS_DFU_IMG_TYPE_APPLICATION 1 +#define LWM2M_OS_DFU_IMG_TYPE_MODEM_DELTA 2 +/** @} */ + +/** + * @brief Find the image type for the buffer of bytes received. * + * @param[in] buf A buffer of bytes which are the start of a binary firmware image. + * @param[in] len The length of the provided buffer. + * + * @return Identifier for a supported image type or LWM2M_OS_DFU_IMG_TYPE_NONE if + * image type is not recognized. + **/ +int lwm2m_os_dfu_img_type(const void *const buf, size_t len); + +/** + * @brief Start a firmware upgrade. + * + * @param[in] img_type DFU target type to be initialized. * @param[in] max_file_size Estimate of the new firmware image to be received. May be greater than * or equal to the actual image size received by the end. + * @param[in] crc_validate Flag to indicate whether to validate the incoming image fragments by + * means of IEEE CRC32. * * @retval 0 Ready to start a new firmware upgrade. * @return A positive number of bytes written so far, if the previous upgrade was not completed. * In this case, the upgrade will resume from this offset. - * @retval -EBUSY Another application firmware upgrade is already ongoing. - * @retval -ENOMEM Not enough memory to store the file of the given size. + * @retval -EBUSY Another firmware upgrade is already ongoing. + * @retval -EFBIG File size exceeds the DFU area size. + * @retval -ENOTSUP Firmware image not supported or unknown. * @retval -EIO Internal error. - * @retval -ENOTSUP This function is not implemented. */ -int lwm2m_os_app_fota_start(size_t max_file_size); +int lwm2m_os_dfu_start(int img_type, size_t max_file_size, bool crc_validate); /** - * @brief Receive an application firmware image fragment and validate its CRC. + * @brief Receive a firmware image fragment and validate its CRC if required. * * @param[in] buf Buffer containing the fragment. * @param[in] len Length of the fragment in bytes. - * @param[in] offset Offset into the buffer, from which to start copying the fragment to flash. - * @param[in] crc32 Expected IEEE CRC32 value. Must be checked for the whole fragment. + * @param[in] crc32 Expected IEEE CRC32 value to be checked for the whole fragment. Can be any + * value if no validation expected. * * @retval 0 Success. - * @retval -EACCES lwm2m_os_app_fota_start() was not called beforehand. - * @retval -ENOMEM Not enough memory to store the file. + * @retval -EACCES lwm2m_os_dfu_start() was not called beforehand. + * @retval -ENOMEM Not enough memory to process the fragment. * @retval -EINVAL CRC error. * @retval -EIO Internal error. - * @retval -ENOTSUP Firmware image not recognized, or this function is not implemented. */ -int lwm2m_os_app_fota_fragment(const char *buf, uint16_t len, uint16_t offset, uint32_t crc32); +int lwm2m_os_dfu_fragment(const char *buf, size_t len, uint32_t crc32); /** - * @brief Finalize the current application firmware upgrade and CRC-validate the image. + * @brief Finalize the current firmware upgrade and CRC-validate the image if required. * - * @param[in] crc32 Expected IEEE CRC32 value. Should be checked for the whole file in flash. + * @param[in] successful Indicate if upload was successful. + * @param[in] crc32 Expected IEEE CRC32 value to be checked for the whole file in flash. + * Can be any value if no validation expected. * * @retval 0 Success. - * @retval -EACCES lwm2m_os_app_fota_start() was not called beforehand. + * @retval -EACCES lwm2m_os_dfu_start() was not called beforehand. * @retval -EINVAL CRC error. * @retval -EIO Internal error. - * @retval -ENOTSUP This function is not implemented. */ -int lwm2m_os_app_fota_finish(uint32_t crc32); +int lwm2m_os_dfu_done(bool successful, uint32_t crc32); + +/** + * @brief Pause the DFU process and release the resources temporarily. + * + * @return A positive number of bytes written so far. + * @retval -EACCES lwm2m_os_dfu_start() was not called beforehand. + * @retval -EIO Internal error. + */ +int lwm2m_os_dfu_pause(void); /** - * @brief Abort the current application firmware upgrade. + * @brief Schedule update for uploaded image. + * + * @retval 0 If success. + */ +int lwm2m_os_dfu_schedule_update(void); + +/** + * @brief Reset the current DFU target. + */ +void lwm2m_os_dfu_reset(void); + +/** + * @brief Validate the application image update. + * + * @retval true If the application image was updated successfully. */ -void lwm2m_os_app_fota_abort(void); +bool lwm2m_os_dfu_application_update_validate(void); #ifdef __cplusplus } diff --git a/lib/bin/lwm2m_carrier/include/lwm2m_settings.h b/lib/bin/lwm2m_carrier/include/lwm2m_settings.h index 816328659d24..3a4e6c29d061 100644 --- a/lib/bin/lwm2m_carrier/include/lwm2m_settings.h +++ b/lib/bin/lwm2m_carrier/include/lwm2m_settings.h @@ -4,6 +4,9 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +#ifndef LWM2M_SETTINGS_H__ +#define LWM2M_SETTINGS_H__ + /** * @file lwm2m_settings.h * @@ -11,9 +14,6 @@ * @{ */ -#ifndef LWM2M_SETTINGS_H__ -#define LWM2M_SETTINGS_H__ - #include #include @@ -41,7 +41,7 @@ int lwm2m_settings_auto_startup_set(bool new_auto_startup); bool lwm2m_settings_enable_custom_config_get(void); /** - * Enable or disable the LwM2M custom settings. + * @brief Enable or disable the LwM2M custom settings. * * @param new_enable_custom_config Whether to enable LwM2M custom settings or not. * @@ -57,7 +57,7 @@ int lwm2m_settings_enable_custom_config_set(bool new_enable_custom_config); uint32_t lwm2m_settings_carriers_enabled_get(void); /** - * Set enabled carriers. + * @brief Set enabled carriers. * * @param new_carriers_enabled Bitmask corresponding to carrier oper_id values. * @@ -90,7 +90,7 @@ int lwm2m_settings_bootstrap_from_smartcard_set(bool new_bootstrap_from_smartcar bool lwm2m_settings_enable_custom_server_config_get(void); /** - * Enable or disable the LwM2M server custom settings. + * @brief Enable or disable the LwM2M server custom settings. * * @param new_enable_custom_server_config Whether to enable LwM2M custom server settings or not. * @@ -199,7 +199,7 @@ int lwm2m_settings_coap_con_interval_set(const int32_t new_coap_con_interval); /** * @brief Retrieve the security tag from the custom LwM2M settings. * - * @retval The security tag + * @retval The security tag. */ uint32_t lwm2m_settings_server_sec_tag_get(void); @@ -252,7 +252,7 @@ int lwm2m_settings_pdn_type_set(uint32_t new_pdn_type); bool lwm2m_settings_enable_custom_device_config_get(void); /** - * Enable or disable the LwM2M device custom settings. + * @brief Enable or disable the LwM2M device custom settings. * * @param new_enable_custom_device_config Whether to enable LwM2M custom device settings or not. * @@ -372,6 +372,38 @@ bool lwm2m_settings_device_serial_no_type_get(void); */ int lwm2m_settings_device_serial_no_type_set(bool new_device_serial_no_type); +/** + * @brief Retrieve the firmware download timeout from the custom LwM2M settings. + * + * @retval The firmware download timeout (in minutes). + */ +uint16_t lwm2m_settings_firmware_download_timeout_get(void); + +/** + * @brief Set or update the firmware download timeout in the custom LwM2M settings. + * + * @param[in] new_firmware_download_timeout Timeout (in minutes). + * + * @retval 0 on success, non-zero on failure. + */ +int lwm2m_settings_firmware_download_timeout_set(const uint16_t new_firmware_download_timeout); + +/** + * @brief Determines whether queue mode is disabled. + * + * @retval true if queue mode enabled. + */ +bool lwm2m_settings_queue_mode_get(void); + +/** + * @brief Enable or disable queue mode. + * + * @param new_queue_mode Whether to enable queue mode or not. + * + * @retval 0 on success, non-zero on failure. + */ +int lwm2m_settings_queue_mode_set(bool new_queue_mode); + /** @} */ #endif /* LWM2M_SETTINGS_H__ */ diff --git a/lib/bin/lwm2m_carrier/lib/cortex-m33/hard-float/liblwm2m_carrier.a b/lib/bin/lwm2m_carrier/lib/cortex-m33/hard-float/liblwm2m_carrier.a index 40761c996ebe..0375a702d475 100644 Binary files a/lib/bin/lwm2m_carrier/lib/cortex-m33/hard-float/liblwm2m_carrier.a and b/lib/bin/lwm2m_carrier/lib/cortex-m33/hard-float/liblwm2m_carrier.a differ diff --git a/lib/bin/lwm2m_carrier/os/lwm2m_carrier.c b/lib/bin/lwm2m_carrier/os/lwm2m_carrier.c index 1a09a1e9badd..fb37eef7b376 100644 --- a/lib/bin/lwm2m_carrier/os/lwm2m_carrier.c +++ b/lib/bin/lwm2m_carrier/os/lwm2m_carrier.c @@ -11,7 +11,6 @@ #include #include -#define LWM2M_CARRIER_THREAD_STACK_SIZE 4096 #define LWM2M_CARRIER_THREAD_PRIORITY K_LOWEST_APPLICATION_THREAD_PRIO NRF_MODEM_LIB_ON_INIT(lwm2m_carrier_init_hook, on_modem_lib_init, NULL); @@ -175,10 +174,6 @@ void lwm2m_carrier_thread_run(void) config.carriers_enabled |= LWM2M_CARRIER_VERIZON; #endif -#ifdef CONFIG_LWM2M_CARRIER_ATT - config.carriers_enabled |= LWM2M_CARRIER_ATT; -#endif - #ifdef CONFIG_LWM2M_CARRIER_LG_UPLUS config.carriers_enabled |= LWM2M_CARRIER_LG_UPLUS; #endif @@ -191,10 +186,18 @@ void lwm2m_carrier_thread_run(void) config.carriers_enabled |= LWM2M_CARRIER_SOFTBANK; #endif +#ifdef CONFIG_LWM2M_CARRIER_BELL_CA + config.carriers_enabled |= LWM2M_CARRIER_BELL_CA; +#endif + #ifndef CONFIG_LWM2M_CARRIER_BOOTSTRAP_SMARTCARD config.disable_bootstrap_from_smartcard = true; #endif +#ifndef CONFIG_LWM2M_CARRIER_QUEUE_MODE + config.disable_queue_mode = true; +#endif + config.server_uri = CONFIG_LWM2M_CARRIER_CUSTOM_URI; #ifdef CONFIG_LWM2M_CARRIER_IS_BOOTSTRAP_SERVER @@ -213,6 +216,7 @@ void lwm2m_carrier_thread_run(void) config.device_type = CONFIG_LWM2M_CARRIER_DEVICE_TYPE; config.hardware_version = CONFIG_LWM2M_CARRIER_DEVICE_HARDWARE_VERSION; config.software_version = CONFIG_LWM2M_CARRIER_DEVICE_SOFTWARE_VERSION; + config.firmware_download_timeout = CONFIG_LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT; #ifdef CONFIG_LWM2M_CARRIER_LG_UPLUS config.lg_uplus.service_code = CONFIG_LWM2M_CARRIER_LG_UPLUS_SERVICE_CODE; @@ -247,6 +251,6 @@ void lwm2m_carrier_thread_run(void) } } -K_THREAD_DEFINE(lwm2m_carrier_thread, LWM2M_CARRIER_THREAD_STACK_SIZE, +K_THREAD_DEFINE(lwm2m_carrier_thread, CONFIG_LWM2M_CARRIER_THREAD_STACK_SIZE, lwm2m_carrier_thread_run, NULL, NULL, NULL, LWM2M_CARRIER_THREAD_PRIORITY, 0, 0); diff --git a/lib/bin/lwm2m_carrier/os/lwm2m_os.c b/lib/bin/lwm2m_carrier/os/lwm2m_os.c index a30c1ecf0891..d16204e0a830 100644 --- a/lib/bin/lwm2m_carrier/os/lwm2m_os.c +++ b/lib/bin/lwm2m_carrier/os/lwm2m_os.c @@ -48,10 +48,6 @@ K_THREAD_STACK_ARRAY_DEFINE(lwm2m_os_work_q_client_stack, LWM2M_OS_MAX_WORK_QS, CONFIG_LWM2M_CARRIER_WORKQ_STACK_SIZE); static struct k_work_q lwm2m_os_work_qs[LWM2M_OS_MAX_WORK_QS]; -K_THREAD_STACK_ARRAY_DEFINE(lwm2m_os_thread_stack, LWM2M_OS_MAX_THREAD_COUNT, - CONFIG_LWM2M_CARRIER_THREAD_STACK_SIZE); -static struct k_thread lwm2m_os_threads[LWM2M_OS_MAX_THREAD_COUNT]; - static struct k_sem lwm2m_os_sems[LWM2M_OS_MAX_SEM_COUNT]; static uint8_t lwm2m_os_sems_used; @@ -341,34 +337,6 @@ bool lwm2m_os_timer_is_pending(lwm2m_os_timer_t *timer) return k_work_delayable_is_pending(&work->work_item); } -/* Thread functions */ - -int lwm2m_os_thread_start(int index, lwm2m_os_thread_entry_t entry, const char *name) -{ - __ASSERT(index < LWM2M_OS_MAX_THREAD_COUNT, "Not enough threads in glue layer"); - - if (index >= LWM2M_OS_MAX_THREAD_COUNT) { - return -EINVAL; - } - - k_tid_t thread = k_thread_create(&lwm2m_os_threads[index], lwm2m_os_thread_stack[index], - K_THREAD_STACK_SIZEOF(lwm2m_os_thread_stack[index]), - entry, NULL, NULL, NULL, K_LOWEST_APPLICATION_THREAD_PRIO, - 0, K_NO_WAIT); - - k_thread_name_set(thread, name); - k_thread_start(thread); - - return 0; -} - -void lwm2m_os_thread_resume(int index) -{ - __ASSERT(index < LWM2M_OS_MAX_THREAD_COUNT, "Invalid thread index"); - - k_thread_resume(&lwm2m_os_threads[index]); -} - int lwm2m_os_sleep(int ms) { k_timeout_t timeout = (ms == -1) ? K_FOREVER : K_MSEC(ms); @@ -475,6 +443,12 @@ int lwm2m_os_download_get(const char *host, const struct lwm2m_os_download_cfg * .pdn_id = cfg->pdn_id, }; + if (cfg->family == LWM2M_OS_PDN_FAM_IPV6) { + config.family = AF_INET6; + } else if (cfg->family == LWM2M_OS_PDN_FAM_IPV4) { + config.family = AF_INET; + } + return download_client_get(&http_downloader, host, &config, NULL, from); } @@ -696,11 +670,6 @@ int lwm2m_os_pdn_id_get(uint8_t cid) return pdn_id_get(cid); } -int lwm2m_os_pdn_default_apn_get(char *buf, size_t len) -{ - return pdn_default_apn_get(buf, len); -} - int lwm2m_os_pdn_default_callback_set(lwm2m_os_pdn_event_handler_t cb) { return pdn_default_ctx_cb_reg((pdn_event_handler_t)cb); @@ -713,15 +682,20 @@ int lwm2m_os_nrf_errno(void) return errno; } -/* Application firmware upgrade abstractions */ - -#if CONFIG_DFU_TARGET_MCUBOOT +/* DFU target handling */ #include + +static bool dfu_in_progress; +static bool dfu_crc_validate; +static int dfu_img_type; + +#if CONFIG_DFU_TARGET_MCUBOOT #include #include #include #include +#include #define MCUBOOT_SECONDARY_ADDR PM_MCUBOOT_SECONDARY_ADDRESS @@ -731,19 +705,11 @@ int lwm2m_os_nrf_errno(void) #define MCUBOOT_SECONDARY_MTD DT_NODELABEL(PM_MCUBOOT_SECONDARY_DEV) #endif -static bool dfu_started; -static bool dfu_in_progress; static uint8_t dfu_stream_buf[1024] __aligned(4); -static void dfu_target_cb(enum dfu_target_evt_id evt_id) -{ - /* This event handler is not in use by LwM2M carrier library. */ - ARG_UNUSED(evt_id); -} - static int crc_validate_fragment(const uint8_t *buf, size_t len, uint32_t crc32) { - if (crc32 != crc32_ieee(buf, len)) { + if ((buf == NULL) || (crc32 != crc32_ieee(buf, len))) { return -EINVAL; } @@ -792,25 +758,72 @@ static int crc_validate_stored_image(size_t len, uint32_t crc32) return 0; } +#else +static int crc_validate_fragment(const uint8_t *buf, size_t len, uint32_t crc32) +{ + ARG_UNUSED(buf); + ARG_UNUSED(len); + ARG_UNUSED(crc32); + + return -EINVAL; +} +#endif /* CONFIG_DFU_TARGET_MCUBOOT */ -int lwm2m_os_app_fota_start(size_t max_file_size) +static void dfu_target_cb(enum dfu_target_evt_id evt_id) { - int err, offset; + /* This event handler is not in use by LwM2M carrier library. */ + ARG_UNUSED(evt_id); +} - if (dfu_started) { +int lwm2m_os_dfu_img_type(const void *const buf, size_t len) +{ + enum dfu_target_image_type type; + + type = dfu_target_img_type(buf, len); + + if (type == DFU_TARGET_IMAGE_TYPE_MCUBOOT) { + return LWM2M_OS_DFU_IMG_TYPE_APPLICATION; + } else if (type == DFU_TARGET_IMAGE_TYPE_MODEM_DELTA) { + return LWM2M_OS_DFU_IMG_TYPE_MODEM_DELTA; + } + + return LWM2M_OS_DFU_IMG_TYPE_NONE; +} + +int lwm2m_os_dfu_start(int img_type, size_t max_file_size, bool crc_validate) +{ + int err; + size_t offset; + + if (dfu_in_progress) { return -EBUSY; } - err = dfu_target_mcuboot_set_buf(dfu_stream_buf, sizeof(dfu_stream_buf)); - if (err) { - return -EIO; + /* A stream buffer is required if the target is MCUBOOT. */ + if (img_type == LWM2M_OS_DFU_IMG_TYPE_APPLICATION) { +#if CONFIG_DFU_TARGET_MCUBOOT + err = dfu_target_mcuboot_set_buf(dfu_stream_buf, sizeof(dfu_stream_buf)); + if (err) { + return -EIO; + } +#else + return -ENOTSUP; +#endif + } else if (img_type != LWM2M_OS_DFU_IMG_TYPE_MODEM_DELTA) { + return -ENOTSUP; } - err = dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, 0, max_file_size, dfu_target_cb); - if (err == -EBUSY) { - return -EBUSY; - } else if ((err == -ENOMEM) || (err == -E2BIG) || (err == -EFBIG)) { - return -ENOMEM; + /* Mark as in progress regardless of the initialization result. The DFU target must be + * reset afterwards to ensure full clean-up. + */ + dfu_in_progress = true; + dfu_img_type = img_type; + dfu_crc_validate = crc_validate; + + err = dfu_target_init(img_type, 0, max_file_size, dfu_target_cb); + if (err == -EFBIG) { + /* Insufficient flash storage for the image. */ + return err; } else if (err) { return -EIO; } @@ -820,139 +833,146 @@ int lwm2m_os_app_fota_start(size_t max_file_size) return -EIO; } - dfu_started = true; - if (offset > 0) { - dfu_in_progress = true; - } - return offset; } -int lwm2m_os_app_fota_fragment(const char *buf, uint16_t len, uint16_t offset, uint32_t crc32) +int lwm2m_os_dfu_fragment(const char *buf, size_t len, uint32_t crc32) { int err; - if ((buf == NULL) || (offset > len)) { - /* Invalid arguments. */ - return -EIO; + if (!dfu_in_progress) { + return -EACCES; } - if (!dfu_started) { - return -EACCES; + /* CRC-validate whole fragment if required. */ + if (dfu_crc_validate) { + err = crc_validate_fragment(buf, len, crc32); + if (err) { + return err; + } } - /* CRC-validate whole fragment. */ - err = crc_validate_fragment(buf, len, crc32); - if (err) { + /* Write fragment. */ + err = dfu_target_write(buf, len); + if ((err == -ENOMEM) || (err == -EINVAL) || (err == -E2BIG)) { + /* Not enough memory to process the fragment, or integrity check failed. */ return err; + } else if (err) { + return -EIO; } + return 0; +} + +int lwm2m_os_dfu_done(bool successful, uint32_t crc32) +{ + int err; + if (!dfu_in_progress) { - /* First fragment. Check image type. */ - if (!dfu_target_mcuboot_identify(buf)) { - lwm2m_os_app_fota_abort(); - return -ENOTSUP; + return -EACCES; + } + +#if CONFIG_DFU_TARGET_MCUBOOT + if (dfu_crc_validate && (dfu_img_type == DFU_TARGET_IMAGE_TYPE_MCUBOOT)) { + size_t offset; + + /* Ensure that the whole image is flushed into flash before CRC-validating it. */ + err = dfu_target_stream_done(true); + if (err) { + return -EIO; } - dfu_in_progress = true; - } + err = dfu_target_stream_offset_get(&offset); + if (err) { + return -EIO; + } - /* Partial write starting from offset. */ - err = dfu_target_write(&buf[offset], len - offset); - if (!err) { - /* Success. */ - return 0; + err = crc_validate_stored_image(offset, crc32); + if (err) { + return err; + } } +#else + ARG_UNUSED(crc32); +#endif /* CONFIG_DFU_TARGET_MCUBOOT */ - /* Cancel DFU and handle error. */ - lwm2m_os_app_fota_abort(); - - if ((err == -ENOMEM) || (err == -E2BIG) || (err == -EFBIG)) { - return -ENOMEM; + err = dfu_target_done(successful); + if (err) { + return -EIO; } - return -EIO; + return 0; } -int lwm2m_os_app_fota_finish(uint32_t crc32) +int lwm2m_os_dfu_pause(void) { - int err = 0; - size_t bytes_written; + int err; + size_t offset; - if (!dfu_started) { + if (!dfu_in_progress) { return -EACCES; } - /* Ensure that the whole image is flushed into flash before CRC-validating it. */ - err = dfu_target_stream_done(true); - if (!err) { - err = dfu_target_stream_offset_get(&bytes_written); - } - if (err) { - err = -EIO; - goto abort; - } + dfu_in_progress = false; - err = crc_validate_stored_image(bytes_written, crc32); + err = dfu_target_done(false); if (err) { - goto abort; + return -EIO; } - err = dfu_target_done(true); - if (!err) { - err = dfu_target_schedule_update(0); - } + err = dfu_target_offset_get(&offset); if (err) { - err = -EIO; - goto abort; + return -EIO; } - return 0; - -abort: - lwm2m_os_app_fota_abort(); - return err; + return offset; } -void lwm2m_os_app_fota_abort(void) +int lwm2m_os_dfu_schedule_update(void) { - if (dfu_started) { - dfu_target_reset(); + int err; - dfu_in_progress = false; - dfu_started = false; + if (!dfu_in_progress) { + return -EACCES; } -} -#else - -int lwm2m_os_app_fota_start(size_t max_file_size) -{ - ARG_UNUSED(max_file_size); + err = dfu_target_schedule_update(0); + if (err == -EINVAL) { + return err; + } else if (err) { + return -EIO; + } - return -ENOTSUP; + return 0; } -int lwm2m_os_app_fota_fragment(const char *buf, uint16_t len, uint16_t offset, uint32_t crc32) +void lwm2m_os_dfu_reset(void) { - ARG_UNUSED(buf); - ARG_UNUSED(len); - ARG_UNUSED(offset); - ARG_UNUSED(crc32); - - return -ENOTSUP; + if (dfu_in_progress) { + dfu_target_reset(); + dfu_in_progress = false; + dfu_img_type = 0; + dfu_crc_validate = false; + } } -int lwm2m_os_app_fota_finish(uint32_t crc32) +__weak bool lwm2m_os_dfu_application_update_validate(void) { - ARG_UNUSED(crc32); +#if CONFIG_BOOTLOADER_MCUBOOT + int err; + bool img_confirmed; + + img_confirmed = boot_is_img_confirmed(); + if (!img_confirmed) { + err = boot_write_img_confirmed(); + if (err == 0) { + LOG_INF("Marked running image as confirmed"); + return true; + } - return -ENOTSUP; -} + LOG_WRN("Failed to mark running image as confirmed"); + } +#endif /* CONFIG_BOOTLOADER_MCUBOOT */ -void lwm2m_os_app_fota_abort(void) -{ - /* Do nothing. */ + return false; } - -#endif /* CONFIG_DFU_TARGET_MCUBOOT */ diff --git a/lib/bin/lwm2m_carrier/os/lwm2m_settings.c b/lib/bin/lwm2m_carrier/os/lwm2m_settings.c index bbd815980a5a..d134eac77b6e 100644 --- a/lib/bin/lwm2m_carrier/os/lwm2m_settings.c +++ b/lib/bin/lwm2m_carrier/os/lwm2m_settings.c @@ -29,6 +29,8 @@ LOG_MODULE_REGISTER(lwm2m_settings, CONFIG_LOG_DEFAULT_LEVEL); #define PDN_TYPE_SETTINGS_KEY "pdn_type" #define SERVICE_CODE_SETTINGS_KEY "service_code" #define DEVICE_SERIAL_NO_TYPE_SETTINGS_KEY "device_serial_no_type" +#define FIRMWARE_DOWNLOAD_TIMEOUT_SETTINGS_KEY "firmware_download_timeout" +#define QUEUE_MODE_KEY "queue_mode" #define ENABLE_CUSTOM_SERVER_SETTINGS_KEY "enable_custom_server_settings" #define IS_BOOTSTRAP_SERVER_SETTINGS_KEY "is_bootstrap_server" @@ -57,6 +59,8 @@ static char apn[64]; static uint32_t pdn_type; static char service_code[6]; static uint8_t device_serial_no_type; +static uint16_t firmware_download_timeout; +static bool queue_mode = true; static bool enable_custom_server_config; static bool is_bootstrap_server; @@ -98,6 +102,10 @@ static int settings_load_cb(const char *key, size_t len, settings_read_cb read_c sz = read_cb(cb_arg, service_code, sizeof(service_code)); } else if (strcmp(key, DEVICE_SERIAL_NO_TYPE_SETTINGS_KEY) == 0) { sz = read_cb(cb_arg, &device_serial_no_type, sizeof(device_serial_no_type)); + } else if (strcmp(key, FIRMWARE_DOWNLOAD_TIMEOUT_SETTINGS_KEY) == 0) { + sz = read_cb(cb_arg, &firmware_download_timeout, sizeof(firmware_download_timeout)); + } else if (strcmp(key, QUEUE_MODE_KEY) == 0) { + sz = read_cb(cb_arg, &queue_mode, sizeof(queue_mode)); } else if (strcmp(key, ENABLE_CUSTOM_SERVER_SETTINGS_KEY) == 0) { sz = read_cb(cb_arg, &enable_custom_server_config, sizeof(enable_custom_server_config)); @@ -139,10 +147,12 @@ static void settings_enable_custom_config(lwm2m_carrier_config_t *config) config->carriers_enabled = carriers_enabled; config->disable_bootstrap_from_smartcard = !bootstrap_from_smartcard; + config->disable_queue_mode = !queue_mode; config->session_idle_timeout = session_idle_timeout; config->coap_con_interval = coap_con_interval; config->apn = apn; config->pdn_type = pdn_type; + config->firmware_download_timeout = firmware_download_timeout; config->lg_uplus.service_code = service_code; config->lg_uplus.device_serial_no_type = device_serial_no_type; } @@ -772,6 +782,43 @@ int lwm2m_settings_device_serial_no_type_set(bool new_device_serial_no_type) return err; } +uint16_t lwm2m_settings_firmware_download_timeout_get(void) +{ + return firmware_download_timeout; +} + +int lwm2m_settings_firmware_download_timeout_set(const uint16_t new_firmware_download_timeout) +{ + firmware_download_timeout = new_firmware_download_timeout; + + int err = settings_save_one(LWM2M_SETTINGS_SUBTREE_NAME "/" + FIRMWARE_DOWNLOAD_TIMEOUT_SETTINGS_KEY, + &firmware_download_timeout, sizeof(firmware_download_timeout)); + if (err) { + LOG_ERR("Save " FIRMWARE_DOWNLOAD_TIMEOUT_SETTINGS_KEY " failed: %d", err); + } + + return err; +} + +bool lwm2m_settings_queue_mode_get(void) +{ + return queue_mode; +} + +int lwm2m_settings_queue_mode_set(bool new_queue_mode) +{ + queue_mode = new_queue_mode; + + int err = settings_save_one(LWM2M_SETTINGS_SUBTREE_NAME "/" QUEUE_MODE_KEY, + &queue_mode, sizeof(queue_mode)); + if (err) { + LOG_ERR("Save " QUEUE_MODE_KEY " failed: %d", err); + } + + return err; +} + int lwm2m_carrier_custom_init(lwm2m_carrier_config_t *config) { int err = settings_init(); diff --git a/lib/bin/lwm2m_carrier/os/lwm2m_shell.c b/lib/bin/lwm2m_carrier/os/lwm2m_shell.c index eb9170479cdc..762359491ec7 100644 --- a/lib/bin/lwm2m_carrier/os/lwm2m_shell.c +++ b/lib/bin/lwm2m_carrier/os/lwm2m_shell.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -32,10 +33,10 @@ static const struct { } carriers_enabled_map[] = { { LWM2M_CARRIER_GENERIC, "Generic" }, { LWM2M_CARRIER_VERIZON, "Verizon" }, - { LWM2M_CARRIER_ATT, "AT&T" }, { LWM2M_CARRIER_LG_UPLUS, "LG U+" }, { LWM2M_CARRIER_T_MOBILE, "T-Mobile" }, - { LWM2M_CARRIER_SOFTBANK, "SoftBank" } + { LWM2M_CARRIER_SOFTBANK, "SoftBank" }, + { LWM2M_CARRIER_BELL_CA, "Bell Canada" } }; static int cmd_device_time_read(const struct shell *shell, size_t argc, char **argv) @@ -701,7 +702,7 @@ static int cmd_device_memory_free_write(const struct shell *shell, size_t argc, return 0; } -static int cmd_log_data_send(const struct shell *shell, size_t argc, char **argv) +static int cmd_log_data_set(const struct shell *shell, size_t argc, char **argv) { if (argc != 2) { shell_print(shell, "%s ", argv[0]); @@ -733,17 +734,17 @@ static int cmd_log_data_send(const struct shell *shell, size_t argc, char **argv return 0; } -static int cmd_app_data_send(const struct shell *shell, size_t argc, char **argv) +static int cmd_app_data_set(const struct shell *shell, size_t argc, char **argv) { if (argc < 2 || argc > 4) { - shell_print(shell, "%s | [ [data]]", - argv[0]); + shell_print(shell, "%s | [ " + "[data]]", argv[0]); shell_print(shell, " The data argument is required if using the App Data " "Container."); shell_print(shell, " When using the Binary App Data Container it is optional,"); shell_print(shell, " not defining it clears the resource instance."); - shell_print(shell, " The instance_id and resource_instance_id arguments are"); - shell_print(shell, " only used when using the Binary App Data Container. "); + shell_print(shell, " The object_instance_id and resource_instance_id arguments"); + shell_print(shell, " are only used when using the Binary App Data Container."); return 0; } @@ -773,7 +774,7 @@ static int cmd_app_data_send(const struct shell *shell, size_t argc, char **argv } } - int err = lwm2m_carrier_app_data_send(path, path_len, buffer, buffer_len); + int err = lwm2m_carrier_app_data_set(path, path_len, buffer, buffer_len); switch (err) { case 0: @@ -796,6 +797,49 @@ static int cmd_app_data_send(const struct shell *shell, size_t argc, char **argv return 0; } +static int cmd_data_send(const struct shell *shell, size_t argc, char **argv) +{ + if (argc != 4 && argc != 5) { + shell_print(shell, "%s " + "[]", argv[0]); + return 0; + } + + uint16_t path[4]; + uint8_t path_len = 3; + + path[0] = (uint16_t)atoi(argv[1]); + path[1] = (uint16_t)atoi(argv[2]); + path[2] = (uint16_t)atoi(argv[3]); + + if (argc == 5) { + path[3] = (uint16_t)atoi(argv[4]); + path_len = 4; + } + + int err = lwm2m_carrier_data_send(path, path_len); + + switch (err) { + case 0: + shell_print(shell, "Sent app data successfully"); + break; + case -EINVAL: + shell_print(shell, "Invalid path"); + break; + case -ENOENT: + shell_print(shell, "Resource at path does not exist"); + break; + case -EINPROGRESS: + shell_print(shell, "Send operation already in progress"); + break; + default: + shell_print(shell, "Unknown error: %d", err); + break; + } + + return 0; +} + static int cmd_request_link_up(const struct shell *shell, size_t argc, char **argv) { int err; @@ -911,7 +955,7 @@ static int cmd_carriers_set(const struct shell *shell, size_t argc, char **argv) { if (argc < 2) { shell_print(shell, "%s all", argv[0]); - shell_print(shell, " All carriers except AT&T"); + shell_print(shell, " All carriers"); shell_print(shell, "%s ...", argv[0]); for (int i = 0; i < ARRAY_SIZE(carriers_enabled_map); i++) { shell_print(shell, " %d = %s", i, carriers_enabled_map[i].name); @@ -962,6 +1006,27 @@ static int cmd_bootstrap_from_smartcard_set(const struct shell *shell, size_t ar return 0; } +static int cmd_queue_mode_set(const struct shell *shell, size_t argc, char **argv) +{ + if (argc != 2) { + shell_print(shell, "%s ", argv[0]); + return 0; + } + + bool queue_mode; + int err = string_to_bool(argv[1], &queue_mode); + + if (!err) { + lwm2m_settings_queue_mode_set(queue_mode); + shell_print(shell, "Set queue mode: %s", + queue_mode ? GREEN "Yes" NORMAL : RED "No" NORMAL); + } else { + shell_print(shell, "Invalid input: "); + } + + return 0; +} + static int cmd_is_bootstrap_server_set(const struct shell *shell, size_t argc, char **argv) { if (argc != 2) { @@ -1100,6 +1165,27 @@ static int cmd_coap_confirmable_interval(const struct shell *shell, size_t argc, return 0; } +static int cmd_firmware_download_timeout_set(const struct shell *shell, size_t argc, char **argv) +{ + if (argc != 2) { + shell_print(shell, "%s ", argv[0]); + return 0; + } + + int32_t firmware_download_timeout = atoi(argv[1]); + + if (firmware_download_timeout < 0 || firmware_download_timeout > UINT16_MAX) { + shell_print(shell, "invalid value, must be between 0 and 65535"); + return 0; + } + + lwm2m_settings_firmware_download_timeout_set(firmware_download_timeout); + + shell_print(shell, "Set firmware download timeout: %d min", firmware_download_timeout); + + return 0; +} + static int cmd_sec_tag_set(const struct shell *shell, size_t argc, char **argv) { if (argc != 2) { @@ -1120,7 +1206,7 @@ static int cmd_sec_tag_set(const struct shell *shell, size_t argc, char **argv) shell_print(shell, "Set security tag: %u", server_sec_tag); if (!provisioned && server_sec_tag != 0) { - shell_print(shell, "Warning: a PSK does not exist in sec_tag %u.", server_sec_tag); + shell_print(shell, "Warning: a PSK does not exist in sec_tag %u", server_sec_tag); shell_print(shell, "This can be written using AT%%CMNG=0,%u,3,\"PSK\"", server_sec_tag); } @@ -1441,6 +1527,8 @@ static int cmd_settings_print(const struct shell *shell, size_t argc, char **arg shell_print(shell, " Carriers enabled %s", carriers_enabled_str()); shell_print(shell, " Bootstrap from smartcard %s", lwm2m_settings_bootstrap_from_smartcard_get() ? "Yes" : "No"); + shell_print(shell, " Queue mode %s", + lwm2m_settings_queue_mode_get() ? "Yes" : "No"); shell_print(shell, " Session idle timeout %d", lwm2m_settings_session_idle_timeout_get()); shell_print(shell, " CoAP confirmable interval %d", @@ -1452,6 +1540,9 @@ static int cmd_settings_print(const struct shell *shell, size_t argc, char **arg lwm2m_settings_service_code_get()); shell_print(shell, " Device Serial Number type %d", lwm2m_settings_device_serial_no_type_get()); + shell_print(shell, " Firmware download timeout %d %s", + lwm2m_settings_firmware_download_timeout_get(), + lwm2m_settings_firmware_download_timeout_get() ? "min" : "(disabled)"); shell_print(shell, ""); shell_print(shell, "Custom carrier server settings %s", lwm2m_settings_enable_custom_server_config_get() ? @@ -1489,13 +1580,13 @@ static int cmd_settings_print(const struct shell *shell, size_t argc, char **arg } SHELL_STATIC_SUBCMD_SET_CREATE(sub_carrier_event_log, - SHELL_CMD(send, NULL, "Send log data using the event log object", - cmd_log_data_send), + SHELL_CMD(set, NULL, "Set log data in the event log object", + cmd_log_data_set), SHELL_SUBCMD_SET_END); SHELL_STATIC_SUBCMD_SET_CREATE(sub_carrier_app_data, - SHELL_CMD(send, NULL, "Send data using an app data container object", - cmd_app_data_send), + SHELL_CMD(set, NULL, "Set data in an app data container object", + cmd_app_data_set), SHELL_SUBCMD_SET_END); SHELL_STATIC_SUBCMD_SET_CREATE(sub_carrier_api_device, @@ -1536,6 +1627,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_carrier_request, SHELL_CMD(link_down, NULL, "Link down", cmd_request_link_down), SHELL_CMD(link_up, NULL, "Link up", cmd_request_link_up), SHELL_CMD(reboot, NULL, "Reboot", cmd_request_reboot), + SHELL_CMD(send, NULL, "Send", cmd_data_send), SHELL_SUBCMD_SET_END /* Array terminated. */ ); @@ -1593,14 +1685,17 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_carrier_config, SHELL_CMD(coap_confirmable_interval, NULL, "CoAP confirmable interval", cmd_coap_confirmable_interval), SHELL_CMD(device, &sub_carrier_config_device, "Device configuration", NULL), + SHELL_CMD(device_serial_no_type, NULL, "Device Serial Number type", + cmd_device_serial_no_type_set), SHELL_CMD(disable, NULL, "Disable custom settings", cmd_disable_set), SHELL_CMD(enable, NULL, "Enable custom settings", cmd_enable_set), + SHELL_CMD(firmware_download_timeout, NULL, "Firmware download timeout", + cmd_firmware_download_timeout_set), SHELL_CMD(pdn_type, NULL, "PDN type", cmd_pdn_type_set), SHELL_CMD(print, NULL, "Print custom settings", cmd_settings_print), + SHELL_CMD(queue_mode, NULL, "Queue mode", cmd_queue_mode_set), SHELL_CMD(server, &sub_carrier_config_server, "Server configuration", NULL), SHELL_CMD(service_code, NULL, "Service code", cmd_service_code_set), - SHELL_CMD(device_serial_no_type, NULL, "Device Serial Number type", - cmd_device_serial_no_type_set), SHELL_CMD(session_idle_timeout, NULL, "Session timeout time", cmd_session_idle_timeout_set), SHELL_SUBCMD_SET_END diff --git a/samples/cellular/http_update/application_update/overlay-carrier.conf b/samples/cellular/http_update/application_update/overlay-carrier.conf index 8c94f1345ee4..36f0fd1dabd1 100644 --- a/samples/cellular/http_update/application_update/overlay-carrier.conf +++ b/samples/cellular/http_update/application_update/overlay-carrier.conf @@ -35,3 +35,6 @@ CONFIG_PM_PARTITION_SIZE_NVS_STORAGE=0 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1536 CONFIG_LWM2M_CARRIER_SETTINGS=n + +# DFU target library +CONFIG_DFU_TARGET=y diff --git a/samples/cellular/http_update/application_update/src/main.c b/samples/cellular/http_update/application_update/src/main.c index 8899788baaf4..57648130ccec 100644 --- a/samples/cellular/http_update/application_update/src/main.c +++ b/samples/cellular/http_update/application_update/src/main.c @@ -498,8 +498,12 @@ int main(void) printk("HTTP application update sample started\n"); printk("Using version %d\n", CONFIG_APPLICATION_VERSION); - /* This is needed so that MCUBoot won't revert the update */ +#if !defined(CONFIG_LWM2M_CARRIER) + /* This is needed so that MCUBoot won't revert the update. + * If the LwM2M Carrier library is enabled, allow the library to confirm the image. + */ boot_write_img_confirmed(); +#endif err = nrf_modem_lib_init(); if (err < 0) { diff --git a/samples/cellular/lwm2m_carrier/prj.conf b/samples/cellular/lwm2m_carrier/prj.conf index f116ae4dd5e4..e947d96d833a 100644 --- a/samples/cellular/lwm2m_carrier/prj.conf +++ b/samples/cellular/lwm2m_carrier/prj.conf @@ -56,3 +56,6 @@ CONFIG_REBOOT=y # Default partition for NVS is unused CONFIG_PM_PARTITION_SIZE_NVS_STORAGE=0 + +# DFU target library +CONFIG_DFU_TARGET=y diff --git a/samples/cellular/modem_shell/overlay-carrier.conf b/samples/cellular/modem_shell/overlay-carrier.conf index 7432657a6b83..b7aa9e7df79d 100644 --- a/samples/cellular/modem_shell/overlay-carrier.conf +++ b/samples/cellular/modem_shell/overlay-carrier.conf @@ -31,3 +31,6 @@ CONFIG_MOSH_FOTA=n CONFIG_BOOTLOADER_MCUBOOT=n CONFIG_IMG_MANAGER=n CONFIG_IMG_ERASE_PROGRESSIVELY=n + +# DFU target library +CONFIG_DFU_TARGET=y diff --git a/samples/cellular/modem_shell/src/main.c b/samples/cellular/modem_shell/src/main.c index 10858df85ff1..5158a4a391de 100644 --- a/samples/cellular/modem_shell/src/main.c +++ b/samples/cellular/modem_shell/src/main.c @@ -337,9 +337,10 @@ int main(void) } #endif /* Application started successfully, mark image as OK to prevent - * revert at next reboot. + * revert at next reboot. If LwM2M Carrier library is enabled, allow + * the library to do it. */ -#if defined(CONFIG_BOOTLOADER_MCUBOOT) +#if (defined(CONFIG_BOOTLOADER_MCUBOOT) && !defined(CONFIG_LWM2M_CARRIER)) boot_write_img_confirmed(); #endif k_poll_signal_init(&mosh_signal);