ec3ec8cd2a
Add macro that allows registration of initialization functions that are called when LwM2M engine starts. On LwM2M engine starts up, it first executes all initialization functions in following priority order: 1. LWM2M_PRIO_ENGINE 2. LWM2M_PRIO_CORE, this is where all LwM2M core objects are initialized 3. LWM2M_PRIO_OBJ, this is where all other objects are initialized 4. LwM2M_PRIO_APP, application initialization. Now on the initialization phase, we could rely that certain objects have already been registered. For example custom objects can register callbacks to core objects. On application phase, we can initialize sensor objects and register their callbacks because objects have already been initialized. This LWM2M_ON_INIT() should replace all use of SYS_INIT() with the default CONFIG_KERNEL_INIT_PRIORITY_DEFAULT. Priority order is actually just alphabetical order of names, so the order is set on a linkin phase, and we don't need any runtime checking for it. Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
379 lines
13 KiB
C
379 lines
13 KiB
C
/*
|
|
* Copyright (c) 2017 Linaro Limited
|
|
* Copyright (c) 2018-2019 Foundries.io
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef LWM2M_ENGINE_H
|
|
#define LWM2M_ENGINE_H
|
|
|
|
#include "lwm2m_message_handling.h"
|
|
#include "lwm2m_object.h"
|
|
#include "lwm2m_observation.h"
|
|
#include "lwm2m_registry.h"
|
|
#include <zephyr/kernel.h>
|
|
|
|
#define LWM2M_PROTOCOL_VERSION_MAJOR 1
|
|
#if defined(CONFIG_LWM2M_VERSION_1_1)
|
|
#define LWM2M_PROTOCOL_VERSION_MINOR 1
|
|
#else
|
|
#define LWM2M_PROTOCOL_VERSION_MINOR 0
|
|
#endif
|
|
|
|
#define LWM2M_PROTOCOL_VERSION_STRING \
|
|
STRINGIFY(LWM2M_PROTOCOL_VERSION_MAJOR) \
|
|
"." STRINGIFY(LWM2M_PROTOCOL_VERSION_MINOR)
|
|
|
|
/* Use this value to generate new token */
|
|
#define LWM2M_MSG_TOKEN_GENERATE_NEW 0xFFU
|
|
|
|
/* length of time in milliseconds to wait for buffer allocations */
|
|
#define BUF_ALLOC_TIMEOUT K_SECONDS(1)
|
|
|
|
/** initialization function */
|
|
struct lwm2m_init_func {
|
|
int (*f)(void);
|
|
};
|
|
/**
|
|
* @defgroup LWM2M_PRIO LwM2M initialization priorities
|
|
* @{
|
|
*/
|
|
#define LWM2M_PRIO_ENGINE 0 /**< Engine initialization */
|
|
#define LWM2M_PRIO_CORE 1 /**< Core object initialization */
|
|
#define LWM2M_PRIO_OBJ 2 /**< Object initializations */
|
|
#define LwM2M_PRIO_APP 3 /**< Application logic initialization */
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief Declare an initialization function to be executed when LwM2M engine starts.
|
|
*
|
|
* When LwM2M engine starts up, it first executes all initialization functions in following
|
|
* priority order:
|
|
* 1. LWM2M_PRIO_ENGINE
|
|
* 2. LWM2M_PRIO_CORE, this is where all LwM2M core objects are initialized
|
|
* 3. LWM2M_PRIO_OBJ, this is where all other than core objects are initialized
|
|
* 4. LwM2M_PRIO_APP, application initialization.
|
|
* For example create sensor objects, and register object callbacks.
|
|
*
|
|
* @param[in] prio Priority, one of @ref LWM2M_PRIO macros.
|
|
* @param[in] init_function Initialization function
|
|
*/
|
|
#define LWM2M_ON_INIT(prio, init_function) \
|
|
STRUCT_SECTION_ITERABLE(lwm2m_init_func, \
|
|
CONCAT(LWM2M, prio, init_function)) = {.f = init_function}
|
|
|
|
/**
|
|
* @brief Declare engine initialization function.
|
|
* @sa LWM2M_ON_INIT
|
|
* @param[in] init_function Initialization function
|
|
*/
|
|
#define LWM2M_ENGINE_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_ENGINE, init_function)
|
|
|
|
/**
|
|
* @brief Declare core object initialization function.
|
|
* @sa LWM2M_ON_INIT
|
|
* @param[in] init_function Initialization function
|
|
*/
|
|
#define LWM2M_CORE_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_CORE, init_function)
|
|
|
|
/**
|
|
* @brief Declare object initialization function.
|
|
* @sa LWM2M_ON_INIT
|
|
* @param[in] init_function Initialization function
|
|
*/
|
|
#define LWM2M_OBJ_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_OBJ, init_function)
|
|
|
|
/**
|
|
* @brief Declare application specific initialization function.
|
|
* @sa LWM2M_ON_INIT
|
|
* @param[in] init_function Initialization function
|
|
*/
|
|
#define LWM2M_APP_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_APP, init_function)
|
|
|
|
/**
|
|
* @brief Validates that writing is a legal operation on the field given by the object in
|
|
* @p obj_inst and the resource id in @p msg. Returns the field to obj_field (if it exists).
|
|
*
|
|
* @param[in] msg lwm2m message to signal for which resource the write access should checked
|
|
* @param[in] obj_inst Engine object instance to signal which object the resource belongs to
|
|
* @param[out] obj_field Engine obejct field buffer pointer to store the field being checked
|
|
* @return 0 for successful validation and negative in all other cases
|
|
*/
|
|
int lwm2m_engine_validate_write_access(struct lwm2m_message *msg,
|
|
struct lwm2m_engine_obj_inst *obj_inst,
|
|
struct lwm2m_engine_obj_field **obj_field);
|
|
|
|
/* LwM2M context functions */
|
|
/**
|
|
* @brief Removes all observes, clears all pending coap messages and resets all messages
|
|
* associated with this context.
|
|
*
|
|
* @param[in] client_ctx Context to close
|
|
*/
|
|
void lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx);
|
|
|
|
/**
|
|
* @brief Initializes a lwm2m_ctx before a socket can be associated with it.
|
|
*
|
|
* @param[in] client_ctx Context to initialize
|
|
*/
|
|
void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx);
|
|
|
|
/* Message buffer functions */
|
|
uint8_t *lwm2m_get_message_buf(void);
|
|
int lwm2m_put_message_buf(uint8_t *buf);
|
|
int lwm2m_perform_composite_observation_op(struct lwm2m_message *msg, uint8_t *token,
|
|
uint8_t token_length, sys_slist_t *lwm2m_path_list);
|
|
|
|
/**
|
|
* @brief Checks if context has access to the object specified by @p path
|
|
*
|
|
* @param[in] client_ctx lwm2m ctx of the connection
|
|
* @param[in] path Path of the object
|
|
* @return Returns false if the bootstrap flag of @p client_ctx is not set
|
|
*/
|
|
bool lwm2m_engine_bootstrap_override(struct lwm2m_ctx *client_ctx, struct lwm2m_obj_path *path);
|
|
|
|
/**
|
|
* @brief Deletes the object instance specified by msg->path. If the object instance id of the
|
|
* path is null (i.e path.level == 1), all object instances of that object will be deleted.
|
|
* Should only be called if delete request comes from a bootstrap server.
|
|
*
|
|
* @param[in] msg lwm2m message with operation delete
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int bootstrap_delete(struct lwm2m_message *msg);
|
|
|
|
/**
|
|
* @brief Adds the periodic @p service to the work queue. The period of the service becomes
|
|
* @p period_ms.
|
|
*
|
|
* @param[in] service Periodic service to be added
|
|
* @param[in] period_ms Period of the periodic service
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_engine_add_service(k_work_handler_t service, uint32_t period_ms);
|
|
|
|
/**
|
|
* @brief Update the period of a given service or remove it.
|
|
*
|
|
* Allow the period modification on an existing service created with
|
|
* lwm2m_engine_add_service(). When period is zero, service is removed.
|
|
*
|
|
* @param[in] service Handler of the periodic_service
|
|
* @param[in] period_ms New period for the periodic_service (in milliseconds) or zero.
|
|
*
|
|
* @return 0 for success, 1 when service was removed or negative in case of error.
|
|
*/
|
|
int lwm2m_engine_update_service_period(k_work_handler_t service, uint32_t period_ms);
|
|
|
|
/**
|
|
* @brief Call specific service handler only once at given timestamp.
|
|
*
|
|
* @param[in] service service to be called
|
|
* @param[in] timestamp Time when to call
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_engine_call_at(k_work_handler_t service, int64_t timestamp);
|
|
|
|
/**
|
|
* @brief Call given handler from engine context.
|
|
*
|
|
* @param[in] service Service callback to be called.
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_engine_call_now(k_work_handler_t service);
|
|
|
|
/**
|
|
* @brief Returns the index in the security objects list corresponding to the object instance
|
|
* id given by @p obj_inst_id
|
|
*
|
|
* @param[in] obj_inst_id object instance id of the security instance
|
|
* @return index in the list or negative in case of error
|
|
*/
|
|
int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id);
|
|
|
|
/**
|
|
* @brief Returns the object instance id of the security having ssid given by @p short_id.
|
|
*
|
|
* @param[in] short_id ssid of the security object
|
|
* @return Object instance id or negative in case not found
|
|
*/
|
|
int lwm2m_security_short_id_to_inst(uint16_t short_id);
|
|
|
|
/**
|
|
* @brief Returns the object instance id of the security object instance at @p index
|
|
* in the security object list.
|
|
*
|
|
* @param[in] index Index in the security object list
|
|
* @return Object instance id of the security instance or negative in case of error
|
|
*/
|
|
int lwm2m_security_index_to_inst_id(int index);
|
|
|
|
#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT)
|
|
/**
|
|
* @brief Sets the update state (as specified in LWM2M SPEC E.6 regarding the firmware update)
|
|
* of the Firmware object instance given by @p obj_inst_id to @p state.
|
|
* (i.e Sets the value of resource 5/ @p obj_inst_id /3)
|
|
*
|
|
* @param[in] obj_inst_id Object instance id of the firmware object instance
|
|
* @param[in] state (STATE_IDLE through STATE_UPDATING)
|
|
*/
|
|
void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state);
|
|
|
|
/**
|
|
* @brief Sets the result state (as specified in LWM2M SPEC E.6 regarding the firmware update)
|
|
* of the Firmware object instance given by @p obj_inst_id to @p result.
|
|
* (i.e Sets the value of resource 5/ @p obj_inst_id /5)
|
|
*
|
|
* @param[in] obj_inst_id Object instance id of the firmware object instance
|
|
* @param[in] result (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
|
|
*/
|
|
void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result);
|
|
|
|
/**
|
|
* @brief Equivalent to lwm2m_firmware_set_update_state_inst(0, state).
|
|
*
|
|
* @param[in] state (STATE_IDLE through STATE_UPDATING)
|
|
*/
|
|
void lwm2m_firmware_set_update_state(uint8_t state);
|
|
|
|
/**
|
|
* @brief Equivalent to lwm2m_firmware_set_update_result_inst(0, result).
|
|
*
|
|
* @param[in] result (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
|
|
*/
|
|
void lwm2m_firmware_set_update_result(uint8_t result);
|
|
|
|
/**
|
|
* @brief Returns the update state (as specified in LWM2M SPEC E.6 regarding the firmware update)
|
|
* of the Firmware object instance given by @p obj_inst_id.
|
|
* (i.e Gets the value of resource 5/ @p obj_inst_id /3)
|
|
* @param[in] obj_inst_id Object instance id of the firmware object
|
|
* @return (STATE_IDLE through STATE_UPDATING)
|
|
*/
|
|
uint8_t lwm2m_firmware_get_update_state_inst(uint16_t obj_inst_id);
|
|
|
|
/**
|
|
* @brief Equivalent to lwm2m_firmware_get_update_state_inst(0).
|
|
*
|
|
* @return (STATE_IDLE through STATE_UPDATING)
|
|
*/
|
|
uint8_t lwm2m_firmware_get_update_state(void);
|
|
|
|
/**
|
|
* @brief Returns the result state (as specified in LWM2M SPEC E.6 regarding the firmware update)
|
|
* of the Firmware object instance given by @p obj_inst_id.
|
|
* (i.e Gets the value of resource 5/ @p obj_inst_id /5)
|
|
* @param[in] obj_inst_id Object instance id of the firmware object
|
|
* @return (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
|
|
*/
|
|
uint8_t lwm2m_firmware_get_update_result_inst(uint16_t obj_inst_id);
|
|
|
|
/**
|
|
* @brief Equivalent to lwm2m_firmware_get_update_result_inst(0).
|
|
*
|
|
* @return (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
|
|
*/
|
|
uint8_t lwm2m_firmware_get_update_result(void);
|
|
#endif
|
|
|
|
/* Network Layer */
|
|
/**
|
|
* @brief Opens a socket for the client_ctx if it does not exist. Saves the
|
|
* socket file descriptor to client_ctx->sock_fd.
|
|
*
|
|
* @param[in] client_ctx lwm2m context to open a socket for
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_open_socket(struct lwm2m_ctx *client_ctx);
|
|
|
|
/**
|
|
* @brief Closes the socket with the file descriptor given by client_ctx->sock_fd.
|
|
* Does nothing if the context's socket is already closed.
|
|
*
|
|
* @param[in, out] client_ctx lwm2m context whose socket is to be closed
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_close_socket(struct lwm2m_ctx *client_ctx);
|
|
|
|
/**
|
|
* @brief Removes the socket with the file descriptor given by client_ctx->sock_fd from the
|
|
* lwm2m work loop. Keeps the socket open.
|
|
*
|
|
* @param[in, out] client_ctx lwm2m context whose socket is being suspended
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_socket_suspend(struct lwm2m_ctx *client_ctx);
|
|
/**
|
|
* @brief Adds an existing socket to the lwm2m work loop. (The socket specified by the file
|
|
* descriptor in ctx->sock_fd)
|
|
*
|
|
* @param[in] ctx lwm2m context being added to the lwm2m work loop
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_socket_add(struct lwm2m_ctx *ctx);
|
|
|
|
/**
|
|
* @brief Removes a socket from the lwm2m work loop.
|
|
*
|
|
* @param[in] ctx lwm2m context to be removed from the lwm2m work loop
|
|
*/
|
|
void lwm2m_socket_del(struct lwm2m_ctx *ctx);
|
|
|
|
/**
|
|
* @brief Creates a socket for the @p client_ctx (if it does not exist) and adds it to
|
|
* the lwm2m work loop.
|
|
*
|
|
* @param client_ctx lwm2m context that the socket is being added for
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_socket_start(struct lwm2m_ctx *client_ctx);
|
|
|
|
/**
|
|
* @brief Closes the socket with file descriptor given by client_ctx->sock_fd.
|
|
*
|
|
* @param client_ctx Context whose socket is being closed
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_socket_close(struct lwm2m_ctx *client_ctx);
|
|
|
|
/**
|
|
* @brief Closes the socket connection when queue mode is enabled.
|
|
*
|
|
* @param[in, out] client_ctx lwm2m context to be closed
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_engine_close_socket_connection(struct lwm2m_ctx *client_ctx);
|
|
|
|
/**
|
|
* @brief Starts the socket of @p client_ctx. Requires CONFIG_LWM2M_DTLS_SUPPORT=y.
|
|
*
|
|
* @param[in] client_ctx lwm2m context to be re-added to the lwm2m work loop
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_engine_connection_resume(struct lwm2m_ctx *client_ctx);
|
|
|
|
/**
|
|
* @brief Moves all queued messages to pending.
|
|
*
|
|
* @param[in, out] client_ctx
|
|
* @return 0 for success or negative in case of error
|
|
*/
|
|
int lwm2m_push_queued_buffers(struct lwm2m_ctx *client_ctx);
|
|
|
|
/* Resources */
|
|
struct lwm2m_ctx **lwm2m_sock_ctx(void);
|
|
int lwm2m_sock_nfds(void);
|
|
|
|
/**
|
|
* @brief Trigger the LwM2M engine to run.
|
|
*
|
|
* This function wakes up ongoing poll() from the socket-loop.
|
|
* It should be called when new transmissions are scheduled or service schedules are modified.
|
|
*/
|
|
void lwm2m_engine_wake_up(void);
|
|
|
|
#endif /* LWM2M_ENGINE_H */
|