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 /*
9 * Copyright (c) 2015, Yanzi Networks AB.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the copyright holder nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*
39 * Original Authors:
40 * Joakim Eriksson <joakime@sics.se>
41 * Niclas Finne <nfi@sics.se>
42 */
43
44 #ifndef LWM2M_OBJECT_H_
45 #define LWM2M_OBJECT_H_
46
47 /* stdint conversions */
48 #include <zephyr/types.h>
49 #include <stddef.h>
50 #include <zephyr/kernel.h>
51
52 #include <zephyr/net/net_ip.h>
53 #include <zephyr/sys/printk.h>
54 #include <zephyr/sys/util.h>
55 #include <sys/types.h>
56 #include <time.h>
57
58 #include <zephyr/net/coap.h>
59 #include <zephyr/net/lwm2m.h>
60
61 #include "buf_util.h"
62
63 /* #####/###/#####/### + NULL */
64 #define MAX_RESOURCE_LEN 20
65
66 /* operations / permissions */
67 /* values from 0 to 7 can be used as permission checks */
68 #define LWM2M_OP_READ 0
69 #define LWM2M_OP_WRITE 1
70 #define LWM2M_OP_CREATE 2
71 #define LWM2M_OP_DELETE 3
72 #define LWM2M_OP_EXECUTE 4
73 #define LWM2M_FLAG_OPTIONAL 7
74 /* values >7 aren't used for permission checks */
75 #define LWM2M_OP_DISCOVER 8
76 #define LWM2M_OP_WRITE_ATTR 9
77
78 /* resource permissions */
79 #define LWM2M_PERM_R BIT(LWM2M_OP_READ)
80 #define LWM2M_PERM_R_OPT (BIT(LWM2M_OP_READ) | \
81 BIT(LWM2M_FLAG_OPTIONAL))
82 #define LWM2M_PERM_W (BIT(LWM2M_OP_WRITE) | \
83 BIT(LWM2M_OP_CREATE))
84 #define LWM2M_PERM_W_OPT (BIT(LWM2M_OP_WRITE) | \
85 BIT(LWM2M_OP_CREATE) | \
86 BIT(LWM2M_FLAG_OPTIONAL))
87 #define LWM2M_PERM_X BIT(LWM2M_OP_EXECUTE)
88 #define LWM2M_PERM_X_OPT (BIT(LWM2M_OP_EXECUTE) | \
89 BIT(LWM2M_FLAG_OPTIONAL))
90 #define LWM2M_PERM_RW (BIT(LWM2M_OP_READ) | \
91 BIT(LWM2M_OP_WRITE) | \
92 BIT(LWM2M_OP_CREATE))
93 #define LWM2M_PERM_RW_OPT (BIT(LWM2M_OP_READ) | \
94 BIT(LWM2M_OP_WRITE) | \
95 BIT(LWM2M_OP_CREATE) | \
96 BIT(LWM2M_FLAG_OPTIONAL))
97 #define LWM2M_PERM_RWX (BIT(LWM2M_OP_READ) | \
98 BIT(LWM2M_OP_WRITE) | \
99 BIT(LWM2M_OP_CREATE) | \
100 BIT(LWM2M_OP_EXECUTE))
101 #define LWM2M_PERM_RWX_OPT (BIT(LWM2M_OP_READ) | \
102 BIT(LWM2M_OP_WRITE) | \
103 BIT(LWM2M_OP_CREATE) | \
104 BIT(LWM2M_OP_EXECUTE) | \
105 BIT(LWM2M_FLAG_OPTIONAL))
106
107 #define LWM2M_HAS_PERM(of, p) (((of)->permissions & p) == p)
108
109 /* resource types */
110 #define LWM2M_RES_TYPE_NONE 0
111 #define LWM2M_RES_TYPE_OPAQUE 1
112 #define LWM2M_RES_TYPE_STRING 2
113 #define LWM2M_RES_TYPE_UINT 3
114 #define LWM2M_RES_TYPE_U32 3
115 #define LWM2M_RES_TYPE_U16 4
116 #define LWM2M_RES_TYPE_U8 5
117 #define LWM2M_RES_TYPE_INT64 6
118 #define LWM2M_RES_TYPE_S64 6
119 #define LWM2M_RES_TYPE_INT 7
120 #define LWM2M_RES_TYPE_S32 7
121 #define LWM2M_RES_TYPE_S16 8
122 #define LWM2M_RES_TYPE_S8 9
123 #define LWM2M_RES_TYPE_BOOL 10
124 #define LWM2M_RES_TYPE_TIME 11
125 #define LWM2M_RES_TYPE_FLOAT 12
126 #define LWM2M_RES_TYPE_OBJLNK 13
127
128 /* remember that we have already output a value - can be between two block's */
129 #define WRITER_OUTPUT_VALUE 1
130 #define WRITER_RESOURCE_INSTANCE 2
131
132 BUILD_ASSERT(CONFIG_LWM2M_COAP_BLOCK_SIZE <= CONFIG_LWM2M_COAP_MAX_MSG_SIZE,
133 "CoAP block size can't exceed maximum message size");
134
135 #define MAX_PACKET_SIZE (CONFIG_LWM2M_COAP_MAX_MSG_SIZE + \
136 CONFIG_LWM2M_ENGINE_MESSAGE_HEADER_SIZE)
137
138 #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER)
139 BUILD_ASSERT(CONFIG_LWM2M_COAP_ENCODE_BUFFER_SIZE >
140 (CONFIG_LWM2M_COAP_BLOCK_SIZE + CONFIG_LWM2M_ENGINE_MESSAGE_HEADER_SIZE),
141 "The buffer for serializing message needs to be bigger than a message with one block");
142 #endif
143
144 /* buffer util macros */
145 #define CPKT_BUF_WRITE(cpkt) (cpkt)->data, &(cpkt)->offset, (cpkt)->max_len
146 #define CPKT_BUF_READ(cpkt) (cpkt)->data, (cpkt)->max_len
147 #define CPKT_BUF_W_PTR(cpkt) ((cpkt)->data + (cpkt)->offset)
148 #define CPKT_BUF_W_SIZE(cpkt) ((cpkt)->max_len - (cpkt)->offset)
149
150 #define CPKT_BUF_W_REGION(cpkt) CPKT_BUF_W_PTR(cpkt), CPKT_BUF_W_SIZE(cpkt)
151
152 /* Input context buffer util macros */
153 #define ICTX_BUF_R_LEFT_SZ(i_ctx) ((i_ctx)->in_cpkt->max_len - (i_ctx)->offset)
154 #define ICTX_BUF_R_PTR(i_ctx) ((i_ctx)->in_cpkt->data + (i_ctx)->offset)
155 #define ICTX_BUF_R_REGION(i_ctx) ICTX_BUF_R_PTR(i_ctx), ICTX_BUF_R_LEFT_SZ(i_ctx)
156
157 struct lwm2m_engine_obj;
158 struct lwm2m_message;
159
160 #define LWM2M_PATH_LEVEL_NONE 0
161 #define LWM2M_PATH_LEVEL_OBJECT 1
162 #define LWM2M_PATH_LEVEL_OBJECT_INST 2
163 #define LWM2M_PATH_LEVEL_RESOURCE 3
164 #define LWM2M_PATH_LEVEL_RESOURCE_INST 4
165
166 /* path representing object instances */
167 #define OBJ_FIELD(_id, _perm, _type) \
168 { .res_id = _id, \
169 .permissions = LWM2M_PERM_ ## _perm, \
170 .data_type = LWM2M_RES_TYPE_ ## _type, }
171
172 /* Keep OBJ_FIELD_DATA around for historical reasons */
173 #define OBJ_FIELD_DATA(res_id, perm, type) \
174 OBJ_FIELD(res_id, perm, type)
175
176 #define OBJ_FIELD_EXECUTE(res_id) \
177 OBJ_FIELD(res_id, X, NONE)
178
179 #define OBJ_FIELD_EXECUTE_OPT(res_id) \
180 OBJ_FIELD(res_id, X_OPT, NONE)
181
182 struct lwm2m_engine_obj_field {
183 uint16_t res_id;
184 uint8_t permissions;
185 uint8_t data_type;
186 };
187
188 typedef struct lwm2m_engine_obj_inst *
189 (*lwm2m_engine_obj_create_cb_t)(uint16_t obj_inst_id);
190
191 struct lwm2m_engine_obj {
192 /* object list */
193 sys_snode_t node;
194
195 /* object field definitions */
196 struct lwm2m_engine_obj_field *fields;
197
198 /* object event callbacks */
199 lwm2m_engine_obj_create_cb_t create_cb;
200 lwm2m_engine_user_cb_t delete_cb;
201 lwm2m_engine_user_cb_t user_create_cb;
202 lwm2m_engine_user_cb_t user_delete_cb;
203
204 /* object member data */
205 uint16_t obj_id;
206 uint16_t field_count;
207 uint16_t instance_count;
208 uint16_t max_instance_count;
209
210 /* Object version information. */
211 uint8_t version_major;
212 uint8_t version_minor;
213
214 /* Object is a core object (defined in the official LwM2M spec.) */
215 bool is_core : 1;
216 };
217
218 /* Resource instances with this value are considered "not created" yet */
219 #define RES_INSTANCE_NOT_CREATED 65535
220
221 /* Resource macros */
222
223 #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0
224 #define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, _multi_ri, \
225 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
226 _r_ptr[_r_idx].res_id = _id; \
227 _r_ptr[_r_idx].res_instances = _ri_ptr; \
228 _r_ptr[_r_idx].res_inst_count = _ri_count; \
229 _r_ptr[_r_idx].multi_res_inst = _multi_ri; \
230 _r_ptr[_r_idx].read_cb = _r_cb; \
231 _r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
232 _r_ptr[_r_idx].validate_cb = _val_cb; \
233 _r_ptr[_r_idx].post_write_cb = _post_w_cb; \
234 _r_ptr[_r_idx].execute_cb = _ex_cb
235 #else
236 #define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, _multi_ri, \
237 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
238 _r_ptr[_r_idx].res_id = _id; \
239 _r_ptr[_r_idx].res_instances = _ri_ptr; \
240 _r_ptr[_r_idx].res_inst_count = _ri_count; \
241 _r_ptr[_r_idx].multi_res_inst = _multi_ri; \
242 _r_ptr[_r_idx].read_cb = _r_cb; \
243 _r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
244 _r_ptr[_r_idx].post_write_cb = _post_w_cb; \
245 _r_ptr[_r_idx].execute_cb = _ex_cb
246 #endif /* CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 */
247
248 #define _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
249 _data_ptr, _data_sz, _data_len) \
250 do { \
251 if (_ri_ptr != NULL && _ri_count > 0) { \
252 for (int _i = 0; _i < _ri_count; _i++) { \
253 _ri_ptr[_ri_idx + _i].data_ptr = \
254 (_data_ptr + _i); \
255 _ri_ptr[_ri_idx + _i].max_data_len = \
256 _data_sz; \
257 _ri_ptr[_ri_idx + _i].data_len = \
258 _data_len; \
259 if (_ri_create) { \
260 _ri_ptr[_ri_idx + _i].res_inst_id = \
261 _i; \
262 } else { \
263 _ri_ptr[_ri_idx + _i].res_inst_id = \
264 RES_INSTANCE_NOT_CREATED; \
265 } \
266 } \
267 } \
268 _ri_idx += _ri_count; \
269 } while (false)
270
271 #define _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create) \
272 do { \
273 if (_ri_count > 0) { \
274 for (int _i = 0; _i < _ri_count; _i++) { \
275 _ri_ptr[_ri_idx + _i].data_ptr = NULL; \
276 _ri_ptr[_ri_idx + _i].max_data_len = 0; \
277 _ri_ptr[_ri_idx + _i].data_len = 0; \
278 if (_ri_create) { \
279 _ri_ptr[_ri_idx + _i].res_inst_id = \
280 _i; \
281 } else { \
282 _ri_ptr[_ri_idx + _i].res_inst_id = \
283 RES_INSTANCE_NOT_CREATED; \
284 } \
285 } \
286 } \
287 _ri_idx += _ri_count; \
288 } while (false)
289
290 #define INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
291 _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
292 _data_ptr, _data_len, \
293 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
294 do { \
295 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
296 (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
297 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
298 _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
299 _data_ptr, _data_len, _data_len); \
300 ++_r_idx; \
301 } while (false)
302
303 #define INIT_OBJ_RES_LEN(_id, _r_ptr, _r_idx, \
304 _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
305 _data_ptr, _data_sz, _data_len, \
306 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
307 do { \
308 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
309 (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
310 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
311 _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
312 _data_ptr, _data_sz, _data_len); \
313 ++_r_idx; \
314 } while (false)
315
316 #define INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
317 _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
318 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
319 do { \
320 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
321 (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
322 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
323 _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create); \
324 ++_r_idx; \
325 } while (false)
326
327 #define INIT_OBJ_RES_MULTI_DATA(_id, _r_ptr, _r_idx, \
328 _ri_ptr, _ri_idx, _ri_count, _ri_create, \
329 _data_ptr, _data_len) \
330 INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
331 _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
332 _data_ptr, _data_len, NULL, NULL, NULL, NULL, NULL)
333
334 #define INIT_OBJ_RES_MULTI_DATA_LEN(_id, _r_ptr, _r_idx, \
335 _ri_ptr, _ri_idx, _ri_count, _ri_create, \
336 _data_ptr, _data_sz, _data_len) \
337 INIT_OBJ_RES_LEN(_id, _r_ptr, _r_idx, \
338 _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
339 _data_ptr, _data_sz, _data_len, NULL, NULL, NULL, NULL, NULL)
340
341 #define INIT_OBJ_RES_MULTI_OPTDATA(_id, _r_ptr, _r_idx, \
342 _ri_ptr, _ri_idx, _ri_count, _ri_create) \
343 INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
344 _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
345 NULL, NULL, NULL, NULL, NULL)
346
347 #define INIT_OBJ_RES_DATA_LEN(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, \
348 _data_ptr, _data_sz, _data_len) \
349 INIT_OBJ_RES_LEN(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, false, true, \
350 _data_ptr, _data_sz, _data_len, NULL, NULL, NULL, NULL, NULL)
351
352 #define INIT_OBJ_RES_DATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, _data_ptr, _data_len) \
353 INIT_OBJ_RES_DATA_LEN(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, _data_ptr, _data_len, \
354 _data_len)
355
356 #define INIT_OBJ_RES_OPTDATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx) \
357 INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, false, \
358 true, NULL, NULL, NULL, NULL, NULL)
359
360 #define INIT_OBJ_RES_EXECUTE(_id, _r_ptr, _r_idx, _ex_cb) \
361 do { \
362 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, NULL, 0, false, \
363 NULL, NULL, NULL, NULL, _ex_cb); \
364 ++_r_idx; \
365 } while (false)
366
367
368 #define LWM2M_ATTR_PMIN 0
369 #define LWM2M_ATTR_PMAX 1
370 #define LWM2M_ATTR_GT 2
371 #define LWM2M_ATTR_LT 3
372 #define LWM2M_ATTR_STEP 4
373 #define NR_LWM2M_ATTR 5
374
375 /* TODO: support multiple server (sec 5.4.2) */
376 struct lwm2m_attr {
377 void *ref;
378
379 /* values */
380 union {
381 double float_val;
382 int32_t int_val;
383 };
384
385 uint8_t type;
386 };
387
388 struct lwm2m_engine_res_inst {
389 void *data_ptr;
390 uint16_t max_data_len;
391 uint16_t data_len;
392 uint16_t res_inst_id; /* 65535 == not "created" */
393 uint8_t data_flags;
394 };
395
396 struct lwm2m_engine_res {
397 lwm2m_engine_get_data_cb_t read_cb;
398 lwm2m_engine_get_data_cb_t pre_write_cb;
399 #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0
400 lwm2m_engine_set_data_cb_t validate_cb;
401 #endif
402 lwm2m_engine_set_data_cb_t post_write_cb;
403 lwm2m_engine_execute_cb_t execute_cb;
404
405 struct lwm2m_engine_res_inst *res_instances;
406 uint16_t res_id;
407 uint8_t res_inst_count;
408 bool multi_res_inst;
409 };
410
411 struct lwm2m_engine_obj_inst {
412 /* instance list */
413 sys_snode_t node;
414
415 struct lwm2m_engine_obj *obj;
416 struct lwm2m_engine_res *resources;
417
418 /* object instance member data */
419 uint16_t obj_inst_id;
420 uint16_t resource_count;
421 };
422
423 /* Initialize resource instances prior to use */
init_res_instance(struct lwm2m_engine_res_inst * ri,size_t ri_len)424 static inline void init_res_instance(struct lwm2m_engine_res_inst *ri,
425 size_t ri_len)
426 {
427 size_t i;
428
429 memset(ri, 0, sizeof(*ri) * ri_len);
430 for (i = 0; i < ri_len; i++) {
431 ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED;
432 }
433 }
434
435 struct lwm2m_opaque_context {
436 size_t len;
437 size_t remaining;
438 };
439
440 struct lwm2m_block_context {
441 struct coap_block_context ctx;
442 struct lwm2m_opaque_context opaque;
443 int64_t timestamp;
444 uint32_t expected;
445 bool last_block : 1;
446 struct lwm2m_obj_path path;
447 };
448
449 struct lwm2m_output_context {
450 const struct lwm2m_writer *writer;
451 struct coap_packet *out_cpkt;
452
453 #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER)
454 /* Corresponding block context. NULL if block transfer is not used. */
455 struct coap_block_context *block_ctx;
456 #endif
457
458 /* private output data */
459 void *user_data;
460 };
461
462 struct lwm2m_input_context {
463 const struct lwm2m_reader *reader;
464 struct coap_packet *in_cpkt;
465
466 /* current position in buffer */
467 uint16_t offset;
468
469 /* Corresponding block context. NULL if block transfer is not used. */
470 struct lwm2m_block_context *block_ctx;
471
472 /* private output data */
473 void *user_data;
474 };
475
476 /* Establish a message timeout callback */
477 typedef void (*lwm2m_message_timeout_cb_t)(struct lwm2m_message *msg);
478
479 /* Internal LwM2M message structure to track in-flight messages. */
480 struct lwm2m_message {
481 sys_snode_t node;
482
483 /** LwM2M context related to this message */
484 struct lwm2m_ctx *ctx;
485
486 /** Incoming / outgoing contexts */
487 struct lwm2m_input_context in;
488 struct lwm2m_output_context out;
489
490 /** Incoming path */
491 struct lwm2m_obj_path path;
492
493 /** CoAP packet data related to the outgoing message */
494 struct coap_packet cpkt;
495
496 /** Buffer data related outgoing message */
497 uint8_t msg_data[MAX_PACKET_SIZE];
498
499 #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER)
500 /** Buffer data containing complete message */
501 struct coap_packet body_encode_buffer;
502 #endif
503
504 /** Message transmission handling for TYPE_CON */
505 struct coap_pending *pending;
506 struct coap_reply *reply;
507 #if defined(CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT)
508 struct lwm2m_cache_read_info *cache_info;
509 #endif
510
511 /** Message configuration */
512 uint8_t *token;
513 coap_reply_t reply_cb;
514 lwm2m_message_timeout_cb_t message_timeout_cb;
515 lwm2m_send_cb_t send_status_cb;
516 uint16_t mid;
517 uint8_t type;
518 uint8_t code;
519 uint8_t tkl;
520
521 /** Incoming message action */
522 uint8_t operation;
523
524 /** Information whether the message was acknowledged. */
525 bool acknowledged : 1;
526
527 /** Indicate that this is part of outgoing block transfer. */
528 bool block_send : 1;
529 };
530
531 /* LWM2M format writer for the various formats supported */
532 struct lwm2m_writer {
533 int (*put_begin)(struct lwm2m_output_context *out,
534 struct lwm2m_obj_path *path);
535 int (*put_end)(struct lwm2m_output_context *out,
536 struct lwm2m_obj_path *path);
537 int (*put_begin_oi)(struct lwm2m_output_context *out,
538 struct lwm2m_obj_path *path);
539 int (*put_end_oi)(struct lwm2m_output_context *out,
540 struct lwm2m_obj_path *path);
541 int (*put_begin_r)(struct lwm2m_output_context *out,
542 struct lwm2m_obj_path *path);
543 int (*put_end_r)(struct lwm2m_output_context *out,
544 struct lwm2m_obj_path *path);
545 int (*put_begin_ri)(struct lwm2m_output_context *out,
546 struct lwm2m_obj_path *path);
547 int (*put_end_ri)(struct lwm2m_output_context *out,
548 struct lwm2m_obj_path *path);
549 int (*put_data_timestamp)(struct lwm2m_output_context *out,
550 time_t value);
551 int (*put_s8)(struct lwm2m_output_context *out,
552 struct lwm2m_obj_path *path, int8_t value);
553 int (*put_s16)(struct lwm2m_output_context *out,
554 struct lwm2m_obj_path *path, int16_t value);
555 int (*put_s32)(struct lwm2m_output_context *out,
556 struct lwm2m_obj_path *path, int32_t value);
557 int (*put_s64)(struct lwm2m_output_context *out,
558 struct lwm2m_obj_path *path, int64_t value);
559 int (*put_time)(struct lwm2m_output_context *out,
560 struct lwm2m_obj_path *path, time_t value);
561 int (*put_string)(struct lwm2m_output_context *out,
562 struct lwm2m_obj_path *path, char *buf,
563 size_t buflen);
564 int (*put_float)(struct lwm2m_output_context *out,
565 struct lwm2m_obj_path *path, double *value);
566 int (*put_bool)(struct lwm2m_output_context *out,
567 struct lwm2m_obj_path *path, bool value);
568 int (*put_opaque)(struct lwm2m_output_context *out,
569 struct lwm2m_obj_path *path, char *buf,
570 size_t buflen);
571 int (*put_objlnk)(struct lwm2m_output_context *out,
572 struct lwm2m_obj_path *path,
573 struct lwm2m_objlnk *value);
574 int (*put_corelink)(struct lwm2m_output_context *out,
575 const struct lwm2m_obj_path *path);
576 };
577
578 struct lwm2m_reader {
579 int (*get_s32)(struct lwm2m_input_context *in, int32_t *value);
580 int (*get_s64)(struct lwm2m_input_context *in, int64_t *value);
581 int (*get_time)(struct lwm2m_input_context *in, time_t *value);
582 int (*get_string)(struct lwm2m_input_context *in, uint8_t *buf,
583 size_t buflen);
584 int (*get_float)(struct lwm2m_input_context *in, double *value);
585 int (*get_bool)(struct lwm2m_input_context *in, bool *value);
586 int (*get_opaque)(struct lwm2m_input_context *in, uint8_t *buf,
587 size_t buflen, struct lwm2m_opaque_context *opaque,
588 bool *last_block);
589 int (*get_objlnk)(struct lwm2m_input_context *in,
590 struct lwm2m_objlnk *value);
591 };
592
593 /* output user_data management functions */
594
engine_set_out_user_data(struct lwm2m_output_context * out,void * user_data)595 static inline void engine_set_out_user_data(struct lwm2m_output_context *out,
596 void *user_data)
597 {
598 out->user_data = user_data;
599 }
600
engine_get_out_user_data(struct lwm2m_output_context * out)601 static inline void *engine_get_out_user_data(struct lwm2m_output_context *out)
602 {
603 return out->user_data;
604 }
605
606 static inline void
engine_clear_out_user_data(struct lwm2m_output_context * out)607 engine_clear_out_user_data(struct lwm2m_output_context *out)
608 {
609 out->user_data = NULL;
610 }
611
engine_set_in_user_data(struct lwm2m_input_context * in,void * user_data)612 static inline void engine_set_in_user_data(struct lwm2m_input_context *in,
613 void *user_data)
614 {
615 in->user_data = user_data;
616 }
617
engine_get_in_user_data(struct lwm2m_input_context * in)618 static inline void *engine_get_in_user_data(struct lwm2m_input_context *in)
619 {
620 return in->user_data;
621 }
622
623 static inline void
engine_clear_in_user_data(struct lwm2m_input_context * in)624 engine_clear_in_user_data(struct lwm2m_input_context *in)
625 {
626 in->user_data = NULL;
627 }
628
629 /* inline multi-format write / read functions */
630
engine_put_begin(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)631 static inline int engine_put_begin(struct lwm2m_output_context *out,
632 struct lwm2m_obj_path *path)
633 {
634 if (out->writer->put_begin) {
635 return out->writer->put_begin(out, path);
636 }
637
638 return 0;
639 }
640
engine_put_end(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)641 static inline int engine_put_end(struct lwm2m_output_context *out,
642 struct lwm2m_obj_path *path)
643 {
644 if (out->writer->put_end) {
645 return out->writer->put_end(out, path);
646 }
647
648 return 0;
649 }
650
engine_put_begin_oi(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)651 static inline int engine_put_begin_oi(struct lwm2m_output_context *out,
652 struct lwm2m_obj_path *path)
653 {
654 if (out->writer->put_begin_oi) {
655 return out->writer->put_begin_oi(out, path);
656 }
657
658 return 0;
659 }
660
engine_put_end_oi(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)661 static inline int engine_put_end_oi(struct lwm2m_output_context *out,
662 struct lwm2m_obj_path *path)
663 {
664 if (out->writer->put_end_oi) {
665 return out->writer->put_end_oi(out, path);
666 }
667
668 return 0;
669 }
670
engine_put_begin_r(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)671 static inline int engine_put_begin_r(struct lwm2m_output_context *out,
672 struct lwm2m_obj_path *path)
673 {
674 if (out->writer->put_begin_r) {
675 return out->writer->put_begin_r(out, path);
676 }
677
678 return 0;
679 }
680
engine_put_end_r(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)681 static inline int engine_put_end_r(struct lwm2m_output_context *out,
682 struct lwm2m_obj_path *path)
683 {
684 if (out->writer->put_end_r) {
685 return out->writer->put_end_r(out, path);
686 }
687
688 return 0;
689 }
690
engine_put_begin_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)691 static inline int engine_put_begin_ri(struct lwm2m_output_context *out,
692 struct lwm2m_obj_path *path)
693 {
694 if (out->writer->put_begin_ri) {
695 return out->writer->put_begin_ri(out, path);
696 }
697
698 return 0;
699 }
700
engine_put_end_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)701 static inline int engine_put_end_ri(struct lwm2m_output_context *out,
702 struct lwm2m_obj_path *path)
703 {
704 if (out->writer->put_end_ri) {
705 return out->writer->put_end_ri(out, path);
706 }
707
708 return 0;
709 }
710
engine_put_s8(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int8_t value)711 static inline int engine_put_s8(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
712 int8_t value)
713 {
714 if (out->writer->put_s8) {
715 return out->writer->put_s8(out, path, value);
716 }
717 return -ENOTSUP;
718 }
719
engine_put_s16(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int16_t value)720 static inline int engine_put_s16(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
721 int16_t value)
722 {
723 if (out->writer->put_s16) {
724 return out->writer->put_s16(out, path, value);
725 }
726 return -ENOTSUP;
727 }
728
engine_put_s32(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int32_t value)729 static inline int engine_put_s32(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
730 int32_t value)
731 {
732 if (out->writer->put_s32) {
733 return out->writer->put_s32(out, path, value);
734 }
735 return -ENOTSUP;
736 }
737
engine_put_s64(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int64_t value)738 static inline int engine_put_s64(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
739 int64_t value)
740 {
741 if (out->writer->put_s64) {
742 return out->writer->put_s64(out, path, value);
743 }
744 return -ENOTSUP;
745 }
746
engine_put_string(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)747 static inline int engine_put_string(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
748 char *buf, size_t buflen)
749 {
750 if (out->writer->put_string) {
751 return out->writer->put_string(out, path, buf, buflen);
752 }
753 return -ENOTSUP;
754 }
755
engine_put_float(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,double * value)756 static inline int engine_put_float(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
757 double *value)
758 {
759 if (out->writer->put_float) {
760 return out->writer->put_float(out, path, value);
761 }
762 return -ENOTSUP;
763 }
764
engine_put_time(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,time_t value)765 static inline int engine_put_time(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
766 time_t value)
767 {
768 if (out->writer->put_time) {
769 return out->writer->put_time(out, path, value);
770 }
771 return -ENOTSUP;
772 }
773
engine_put_bool(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,bool value)774 static inline int engine_put_bool(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
775 bool value)
776 {
777 if (out->writer->put_bool) {
778 return out->writer->put_bool(out, path, value);
779 }
780 return -ENOTSUP;
781 }
782
engine_put_opaque(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)783 static inline int engine_put_opaque(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
784 char *buf, size_t buflen)
785 {
786 if (out->writer->put_opaque) {
787 return out->writer->put_opaque(out, path, buf, buflen);
788 }
789
790 return -ENOTSUP;
791 }
792
engine_put_objlnk(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,struct lwm2m_objlnk * value)793 static inline int engine_put_objlnk(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
794 struct lwm2m_objlnk *value)
795 {
796 if (out->writer->put_objlnk) {
797 return out->writer->put_objlnk(out, path, value);
798 }
799 return -ENOTSUP;
800 }
801
engine_put_corelink(struct lwm2m_output_context * out,const struct lwm2m_obj_path * path)802 static inline int engine_put_corelink(struct lwm2m_output_context *out,
803 const struct lwm2m_obj_path *path)
804 {
805 if (out->writer->put_corelink) {
806 return out->writer->put_corelink(out, path);
807 }
808
809 return -ENOTSUP;
810 }
811
engine_put_timestamp(struct lwm2m_output_context * out,time_t timestamp)812 static inline int engine_put_timestamp(struct lwm2m_output_context *out, time_t timestamp)
813 {
814 if (out->writer->put_data_timestamp) {
815 return out->writer->put_data_timestamp(out, timestamp);
816 }
817
818 return -ENOTSUP;
819 }
820
engine_get_s32(struct lwm2m_input_context * in,int32_t * value)821 static inline int engine_get_s32(struct lwm2m_input_context *in, int32_t *value)
822 {
823 if (in->reader->get_s32) {
824 return in->reader->get_s32(in, value);
825 }
826 return -ENOTSUP;
827 }
828
engine_get_s64(struct lwm2m_input_context * in,int64_t * value)829 static inline int engine_get_s64(struct lwm2m_input_context *in, int64_t *value)
830 {
831 if (in->reader->get_s64) {
832 return in->reader->get_s64(in, value);
833 }
834 return -ENOTSUP;
835 }
836
engine_get_string(struct lwm2m_input_context * in,uint8_t * buf,size_t buflen)837 static inline int engine_get_string(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen)
838 {
839 if (in->reader->get_string) {
840 return in->reader->get_string(in, buf, buflen);
841 }
842 return -ENOTSUP;
843 }
844
engine_get_time(struct lwm2m_input_context * in,time_t * value)845 static inline int engine_get_time(struct lwm2m_input_context *in, time_t *value)
846 {
847 if (in->reader->get_time) {
848 return in->reader->get_time(in, value);
849 }
850 return -ENOTSUP;
851 }
852
engine_get_float(struct lwm2m_input_context * in,double * value)853 static inline int engine_get_float(struct lwm2m_input_context *in, double *value)
854 {
855 if (in->reader->get_float) {
856 return in->reader->get_float(in, value);
857 }
858 return -ENOTSUP;
859 }
860
engine_get_bool(struct lwm2m_input_context * in,bool * value)861 static inline int engine_get_bool(struct lwm2m_input_context *in, bool *value)
862 {
863 if (in->reader->get_bool) {
864 return in->reader->get_bool(in, value);
865 }
866 return -ENOTSUP;
867 }
868
engine_get_opaque(struct lwm2m_input_context * in,uint8_t * buf,size_t buflen,struct lwm2m_opaque_context * opaque,bool * last_block)869 static inline int engine_get_opaque(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen,
870 struct lwm2m_opaque_context *opaque, bool *last_block)
871 {
872 if (in->reader->get_opaque) {
873 return in->reader->get_opaque(in, buf, buflen, opaque, last_block);
874 }
875
876 return -ENOTSUP;
877 }
878
engine_get_objlnk(struct lwm2m_input_context * in,struct lwm2m_objlnk * value)879 static inline int engine_get_objlnk(struct lwm2m_input_context *in, struct lwm2m_objlnk *value)
880 {
881 if (in->reader->get_objlnk) {
882 return in->reader->get_objlnk(in, value);
883 }
884 return -ENOTSUP;
885 }
886
887 #endif /* LWM2M_OBJECT_H_ */
888