1 /* 2 * Copyright (c) 2017 Linaro Limited 3 * Copyright (c) 2018-2019 Foundries.io 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 #ifndef LWM2M_ENGINE_H 9 #define LWM2M_ENGINE_H 10 11 #include "lwm2m_message_handling.h" 12 #include "lwm2m_object.h" 13 #include "lwm2m_observation.h" 14 #include "lwm2m_registry.h" 15 #include <zephyr/kernel.h> 16 17 #define LWM2M_PROTOCOL_VERSION_MAJOR 1 18 #if defined(CONFIG_LWM2M_VERSION_1_1) 19 #define LWM2M_PROTOCOL_VERSION_MINOR 1 20 #else 21 #define LWM2M_PROTOCOL_VERSION_MINOR 0 22 #endif 23 24 #define LWM2M_PROTOCOL_VERSION_STRING \ 25 STRINGIFY(LWM2M_PROTOCOL_VERSION_MAJOR) \ 26 "." STRINGIFY(LWM2M_PROTOCOL_VERSION_MINOR) 27 28 /* Use this value to generate new token */ 29 #define LWM2M_MSG_TOKEN_GENERATE_NEW 0xFFU 30 31 /* length of time in milliseconds to wait for buffer allocations */ 32 #define BUF_ALLOC_TIMEOUT K_SECONDS(1) 33 34 /** initialization function */ 35 struct lwm2m_init_func { 36 int (*f)(void); 37 }; 38 /** 39 * @defgroup LWM2M_PRIO LwM2M initialization priorities 40 * @{ 41 */ 42 #define LWM2M_PRIO_ENGINE 0 /**< Engine initialization */ 43 #define LWM2M_PRIO_CORE 1 /**< Core object initialization */ 44 #define LWM2M_PRIO_OBJ 2 /**< Object initializations */ 45 #define LwM2M_PRIO_APP 3 /**< Application logic initialization */ 46 /** @} */ 47 48 /** 49 * @brief Declare an initialization function to be executed when LwM2M engine starts. 50 * 51 * When LwM2M engine starts up, it first executes all initialization functions in following 52 * priority order: 53 * 1. LWM2M_PRIO_ENGINE 54 * 2. LWM2M_PRIO_CORE, this is where all LwM2M core objects are initialized 55 * 3. LWM2M_PRIO_OBJ, this is where all other than core objects are initialized 56 * 4. LwM2M_PRIO_APP, application initialization. 57 * For example create sensor objects, and register object callbacks. 58 * 59 * @param[in] prio Priority, one of @ref LWM2M_PRIO macros. 60 * @param[in] init_function Initialization function 61 */ 62 #define LWM2M_ON_INIT(prio, init_function) \ 63 STRUCT_SECTION_ITERABLE(lwm2m_init_func, \ 64 CONCAT(LWM2M, prio, init_function)) = {.f = init_function} 65 66 /** 67 * @brief Declare engine initialization function. 68 * @sa LWM2M_ON_INIT 69 * @param[in] init_function Initialization function 70 */ 71 #define LWM2M_ENGINE_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_ENGINE, init_function) 72 73 /** 74 * @brief Declare core object initialization function. 75 * @sa LWM2M_ON_INIT 76 * @param[in] init_function Initialization function 77 */ 78 #define LWM2M_CORE_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_CORE, init_function) 79 80 /** 81 * @brief Declare object initialization function. 82 * @sa LWM2M_ON_INIT 83 * @param[in] init_function Initialization function 84 */ 85 #define LWM2M_OBJ_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_OBJ, init_function) 86 87 /** 88 * @brief Declare application specific initialization function. 89 * @sa LWM2M_ON_INIT 90 * @param[in] init_function Initialization function 91 */ 92 #define LWM2M_APP_INIT(init_function) LWM2M_ON_INIT(LWM2M_PRIO_APP, init_function) 93 94 /** 95 * @brief Validates that writing is a legal operation on the field given by the object in 96 * @p obj_inst and the resource id in @p msg. Returns the field to obj_field (if it exists). 97 * 98 * @param[in] msg lwm2m message to signal for which resource the write access should checked 99 * @param[in] obj_inst Engine object instance to signal which object the resource belongs to 100 * @param[out] obj_field Engine obejct field buffer pointer to store the field being checked 101 * @return 0 for successful validation and negative in all other cases 102 */ 103 int lwm2m_engine_validate_write_access(struct lwm2m_message *msg, 104 struct lwm2m_engine_obj_inst *obj_inst, 105 struct lwm2m_engine_obj_field **obj_field); 106 107 /* LwM2M context functions */ 108 /** 109 * @brief Removes all observes, clears all pending coap messages and resets all messages 110 * associated with this context. 111 * 112 * @param[in] client_ctx Context to close 113 */ 114 void lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx); 115 116 /** 117 * @brief Initializes a lwm2m_ctx before a socket can be associated with it. 118 * 119 * @param[in] client_ctx Context to initialize 120 */ 121 void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx); 122 123 /* Message buffer functions */ 124 uint8_t *lwm2m_get_message_buf(void); 125 int lwm2m_put_message_buf(uint8_t *buf); 126 int lwm2m_perform_composite_observation_op(struct lwm2m_message *msg, uint8_t *token, 127 uint8_t token_length, sys_slist_t *lwm2m_path_list); 128 129 /** 130 * @brief Checks if context has access to the object specified by @p path 131 * 132 * @param[in] client_ctx lwm2m ctx of the connection 133 * @param[in] path Path of the object 134 * @return Returns false if the bootstrap flag of @p client_ctx is not set 135 */ 136 bool lwm2m_engine_bootstrap_override(struct lwm2m_ctx *client_ctx, struct lwm2m_obj_path *path); 137 138 /** 139 * @brief Deletes the object instance specified by msg->path. If the object instance id of the 140 * path is null (i.e path.level == 1), all object instances of that object will be deleted. 141 * Should only be called if delete request comes from a bootstrap server. 142 * 143 * @param[in] msg lwm2m message with operation delete 144 * @return 0 for success or negative in case of error 145 */ 146 int bootstrap_delete(struct lwm2m_message *msg); 147 148 /** 149 * @brief Adds the periodic @p service to the work queue. The period of the service becomes 150 * @p period_ms. 151 * 152 * @param[in] service Periodic service to be added 153 * @param[in] period_ms Period of the periodic service 154 * @return 0 for success or negative in case of error 155 */ 156 int lwm2m_engine_add_service(k_work_handler_t service, uint32_t period_ms); 157 158 /** 159 * @brief Update the period of a given service or remove it. 160 * 161 * Allow the period modification on an existing service created with 162 * lwm2m_engine_add_service(). When period is zero, service is removed. 163 * 164 * @param[in] service Handler of the periodic_service 165 * @param[in] period_ms New period for the periodic_service (in milliseconds) or zero. 166 * 167 * @return 0 for success, 1 when service was removed or negative in case of error. 168 */ 169 int lwm2m_engine_update_service_period(k_work_handler_t service, uint32_t period_ms); 170 171 /** 172 * @brief Call specific service handler only once at given timestamp. 173 * 174 * @param[in] service service to be called 175 * @param[in] timestamp Time when to call 176 * @return 0 for success or negative in case of error 177 */ 178 int lwm2m_engine_call_at(k_work_handler_t service, int64_t timestamp); 179 180 /** 181 * @brief Call given handler from engine context. 182 * 183 * @param[in] service Service callback to be called. 184 * @return 0 for success or negative in case of error 185 */ 186 int lwm2m_engine_call_now(k_work_handler_t service); 187 188 /** 189 * @brief Returns the index in the security objects list corresponding to the object instance 190 * id given by @p obj_inst_id 191 * 192 * @param[in] obj_inst_id object instance id of the security instance 193 * @return index in the list or negative in case of error 194 */ 195 int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id); 196 197 /** 198 * @brief Returns the object instance id of the security having ssid given by @p short_id. 199 * 200 * @param[in] short_id ssid of the security object 201 * @return Object instance id or negative in case not found 202 */ 203 int lwm2m_security_short_id_to_inst(uint16_t short_id); 204 205 /** 206 * @brief Returns the object instance id of the security object instance at @p index 207 * in the security object list. 208 * 209 * @param[in] index Index in the security object list 210 * @return Object instance id of the security instance or negative in case of error 211 */ 212 int lwm2m_security_index_to_inst_id(int index); 213 214 #if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT) 215 /** 216 * @brief Sets the update state (as specified in LWM2M SPEC E.6 regarding the firmware update) 217 * of the Firmware object instance given by @p obj_inst_id to @p state. 218 * (i.e Sets the value of resource 5/ @p obj_inst_id /3) 219 * 220 * @param[in] obj_inst_id Object instance id of the firmware object instance 221 * @param[in] state (STATE_IDLE through STATE_UPDATING) 222 */ 223 void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state); 224 225 /** 226 * @brief Sets the result state (as specified in LWM2M SPEC E.6 regarding the firmware update) 227 * of the Firmware object instance given by @p obj_inst_id to @p result. 228 * (i.e Sets the value of resource 5/ @p obj_inst_id /5) 229 * 230 * @param[in] obj_inst_id Object instance id of the firmware object instance 231 * @param[in] result (RESULT_DEFAULT through RESULT_UNSUP_PROTO) 232 */ 233 void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result); 234 235 /** 236 * @brief Equivalent to lwm2m_firmware_set_update_state_inst(0, state). 237 * 238 * @param[in] state (STATE_IDLE through STATE_UPDATING) 239 */ 240 void lwm2m_firmware_set_update_state(uint8_t state); 241 242 /** 243 * @brief Equivalent to lwm2m_firmware_set_update_result_inst(0, result). 244 * 245 * @param[in] result (RESULT_DEFAULT through RESULT_UNSUP_PROTO) 246 */ 247 void lwm2m_firmware_set_update_result(uint8_t result); 248 249 /** 250 * @brief Returns the update state (as specified in LWM2M SPEC E.6 regarding the firmware update) 251 * of the Firmware object instance given by @p obj_inst_id. 252 * (i.e Gets the value of resource 5/ @p obj_inst_id /3) 253 * @param[in] obj_inst_id Object instance id of the firmware object 254 * @return (STATE_IDLE through STATE_UPDATING) 255 */ 256 uint8_t lwm2m_firmware_get_update_state_inst(uint16_t obj_inst_id); 257 258 /** 259 * @brief Equivalent to lwm2m_firmware_get_update_state_inst(0). 260 * 261 * @return (STATE_IDLE through STATE_UPDATING) 262 */ 263 uint8_t lwm2m_firmware_get_update_state(void); 264 265 /** 266 * @brief Returns the result state (as specified in LWM2M SPEC E.6 regarding the firmware update) 267 * of the Firmware object instance given by @p obj_inst_id. 268 * (i.e Gets the value of resource 5/ @p obj_inst_id /5) 269 * @param[in] obj_inst_id Object instance id of the firmware object 270 * @return (RESULT_DEFAULT through RESULT_UNSUP_PROTO) 271 */ 272 uint8_t lwm2m_firmware_get_update_result_inst(uint16_t obj_inst_id); 273 274 /** 275 * @brief Equivalent to lwm2m_firmware_get_update_result_inst(0). 276 * 277 * @return (RESULT_DEFAULT through RESULT_UNSUP_PROTO) 278 */ 279 uint8_t lwm2m_firmware_get_update_result(void); 280 #endif 281 282 /* Network Layer */ 283 /** 284 * @brief Opens a socket for the client_ctx if it does not exist. Saves the 285 * socket file descriptor to client_ctx->sock_fd. 286 * 287 * @param[in] client_ctx lwm2m context to open a socket for 288 * @return 0 for success or negative in case of error 289 */ 290 int lwm2m_open_socket(struct lwm2m_ctx *client_ctx); 291 292 /** 293 * @brief Closes the socket with the file descriptor given by client_ctx->sock_fd. 294 * Does nothing if the context's socket is already closed. 295 * 296 * @param[in, out] client_ctx lwm2m context whose socket is to be closed 297 * @return 0 for success or negative in case of error 298 */ 299 int lwm2m_close_socket(struct lwm2m_ctx *client_ctx); 300 301 /** 302 * @brief Removes the socket with the file descriptor given by client_ctx->sock_fd from the 303 * lwm2m work loop. Keeps the socket open. 304 * 305 * @param[in, out] client_ctx lwm2m context whose socket is being suspended 306 * @return 0 for success or negative in case of error 307 */ 308 int lwm2m_socket_suspend(struct lwm2m_ctx *client_ctx); 309 /** 310 * @brief Adds an existing socket to the lwm2m work loop. (The socket specified by the file 311 * descriptor in ctx->sock_fd) 312 * 313 * @param[in] ctx lwm2m context being added to the lwm2m work loop 314 * @return 0 for success or negative in case of error 315 */ 316 int lwm2m_socket_add(struct lwm2m_ctx *ctx); 317 318 /** 319 * @brief Removes a socket from the lwm2m work loop. 320 * 321 * @param[in] ctx lwm2m context to be removed from the lwm2m work loop 322 */ 323 void lwm2m_socket_del(struct lwm2m_ctx *ctx); 324 325 /** 326 * @brief Creates a socket for the @p client_ctx (if it does not exist) and adds it to 327 * the lwm2m work loop. 328 * 329 * @param client_ctx lwm2m context that the socket is being added for 330 * @return 0 for success or negative in case of error 331 */ 332 int lwm2m_socket_start(struct lwm2m_ctx *client_ctx); 333 334 /** 335 * @brief Closes the socket with file descriptor given by client_ctx->sock_fd. 336 * 337 * @param client_ctx Context whose socket is being closed 338 * @return 0 for success or negative in case of error 339 */ 340 int lwm2m_socket_close(struct lwm2m_ctx *client_ctx); 341 342 /** 343 * @brief Closes the socket connection when queue mode is enabled. 344 * 345 * @param[in, out] client_ctx lwm2m context to be closed 346 * @return 0 for success or negative in case of error 347 */ 348 int lwm2m_engine_close_socket_connection(struct lwm2m_ctx *client_ctx); 349 350 /** 351 * @brief Starts the socket of @p client_ctx. Requires CONFIG_LWM2M_DTLS_SUPPORT=y. 352 * 353 * @param[in] client_ctx lwm2m context to be re-added to the lwm2m work loop 354 * @return 0 for success or negative in case of error 355 */ 356 int lwm2m_engine_connection_resume(struct lwm2m_ctx *client_ctx); 357 358 /** 359 * @brief Moves all queued messages to pending. 360 * 361 * @param[in, out] client_ctx 362 * @return 0 for success or negative in case of error 363 */ 364 int lwm2m_push_queued_buffers(struct lwm2m_ctx *client_ctx); 365 366 /* Resources */ 367 struct lwm2m_ctx **lwm2m_sock_ctx(void); 368 int lwm2m_sock_nfds(void); 369 370 /** 371 * @brief Trigger the LwM2M engine to run. 372 * 373 * This function wakes up ongoing poll() from the socket-loop. 374 * It should be called when new transmissions are scheduled or service schedules are modified. 375 */ 376 void lwm2m_engine_wake_up(void); 377 378 #endif /* LWM2M_ENGINE_H */ 379