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 BUILD_ASSERT(CONFIG_LWM2M_COAP_BLOCK_SIZE == 64 ||
135 CONFIG_LWM2M_COAP_BLOCK_SIZE == 128 ||
136 CONFIG_LWM2M_COAP_BLOCK_SIZE == 256 ||
137 CONFIG_LWM2M_COAP_BLOCK_SIZE == 512 ||
138 CONFIG_LWM2M_COAP_BLOCK_SIZE == 1024,
139 "CoAP block must be 64, 128, 256, 512 or 1024");
140
141 /* buffer util macros */
142 #define CPKT_BUF_WRITE(cpkt) (cpkt)->data, &(cpkt)->offset, (cpkt)->max_len
143 #define CPKT_BUF_READ(cpkt) (cpkt)->data, (cpkt)->max_len
144 #define CPKT_BUF_W_PTR(cpkt) ((cpkt)->data + (cpkt)->offset)
145 #define CPKT_BUF_W_SIZE(cpkt) ((cpkt)->max_len - (cpkt)->offset)
146
147 #define CPKT_BUF_W_REGION(cpkt) CPKT_BUF_W_PTR(cpkt), CPKT_BUF_W_SIZE(cpkt)
148
149 /* Input context buffer util macros */
150 #define ICTX_BUF_R_LEFT_SZ(i_ctx) ((i_ctx)->in_cpkt->max_len - (i_ctx)->offset)
151 #define ICTX_BUF_R_PTR(i_ctx) ((i_ctx)->in_cpkt->data + (i_ctx)->offset)
152 #define ICTX_BUF_R_REGION(i_ctx) ICTX_BUF_R_PTR(i_ctx), ICTX_BUF_R_LEFT_SZ(i_ctx)
153
154 struct lwm2m_engine_obj;
155 struct lwm2m_message;
156
157 #define LWM2M_PATH_LEVEL_NONE 0
158 #define LWM2M_PATH_LEVEL_OBJECT 1
159 #define LWM2M_PATH_LEVEL_OBJECT_INST 2
160 #define LWM2M_PATH_LEVEL_RESOURCE 3
161 #define LWM2M_PATH_LEVEL_RESOURCE_INST 4
162
163 /* path representing object instances */
164 #define OBJ_FIELD(_id, _perm, _type) \
165 { .res_id = _id, \
166 .permissions = LWM2M_PERM_ ## _perm, \
167 .data_type = LWM2M_RES_TYPE_ ## _type, }
168
169 /* Keep OBJ_FIELD_DATA around for historical reasons */
170 #define OBJ_FIELD_DATA(res_id, perm, type) \
171 OBJ_FIELD(res_id, perm, type)
172
173 #define OBJ_FIELD_EXECUTE(res_id) \
174 OBJ_FIELD(res_id, X, NONE)
175
176 #define OBJ_FIELD_EXECUTE_OPT(res_id) \
177 OBJ_FIELD(res_id, X_OPT, NONE)
178
179 struct lwm2m_engine_obj_field {
180 uint16_t res_id;
181 uint8_t permissions;
182 uint8_t data_type;
183 };
184
185 typedef struct lwm2m_engine_obj_inst *
186 (*lwm2m_engine_obj_create_cb_t)(uint16_t obj_inst_id);
187
188 struct lwm2m_engine_obj {
189 /* object list */
190 sys_snode_t node;
191
192 /* object field definitions */
193 struct lwm2m_engine_obj_field *fields;
194
195 /* object event callbacks */
196 lwm2m_engine_obj_create_cb_t create_cb;
197 lwm2m_engine_user_cb_t delete_cb;
198 lwm2m_engine_user_cb_t user_create_cb;
199 lwm2m_engine_user_cb_t user_delete_cb;
200
201 /* object member data */
202 uint16_t obj_id;
203 uint16_t field_count;
204 uint16_t instance_count;
205 uint16_t max_instance_count;
206
207 /* Object version information. */
208 uint8_t version_major;
209 uint8_t version_minor;
210
211 /* Object is a core object (defined in the official LwM2M spec.) */
212 bool is_core : 1;
213 };
214
215 /* Resource instances with this value are considered "not created" yet */
216 #define RES_INSTANCE_NOT_CREATED 65535
217
218 /* Resource macros */
219
220 #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0
221 #define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, _multi_ri, \
222 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
223 _r_ptr[_r_idx].res_id = _id; \
224 _r_ptr[_r_idx].res_instances = _ri_ptr; \
225 _r_ptr[_r_idx].res_inst_count = _ri_count; \
226 _r_ptr[_r_idx].multi_res_inst = _multi_ri; \
227 _r_ptr[_r_idx].read_cb = _r_cb; \
228 _r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
229 _r_ptr[_r_idx].validate_cb = _val_cb; \
230 _r_ptr[_r_idx].post_write_cb = _post_w_cb; \
231 _r_ptr[_r_idx].execute_cb = _ex_cb
232 #else
233 #define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, _multi_ri, \
234 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
235 _r_ptr[_r_idx].res_id = _id; \
236 _r_ptr[_r_idx].res_instances = _ri_ptr; \
237 _r_ptr[_r_idx].res_inst_count = _ri_count; \
238 _r_ptr[_r_idx].multi_res_inst = _multi_ri; \
239 _r_ptr[_r_idx].read_cb = _r_cb; \
240 _r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
241 _r_ptr[_r_idx].post_write_cb = _post_w_cb; \
242 _r_ptr[_r_idx].execute_cb = _ex_cb
243 #endif /* CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 */
244
245 #define _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
246 _data_ptr, _data_sz, _data_len) \
247 do { \
248 if (_ri_ptr != NULL && _ri_count > 0) { \
249 for (int _i = 0; _i < _ri_count; _i++) { \
250 _ri_ptr[_ri_idx + _i].data_ptr = \
251 ((uint8_t *) _data_ptr + (_i * _data_sz)); \
252 _ri_ptr[_ri_idx + _i].max_data_len = \
253 _data_sz; \
254 _ri_ptr[_ri_idx + _i].data_len = \
255 _data_len; \
256 if (_ri_create) { \
257 _ri_ptr[_ri_idx + _i].res_inst_id = \
258 _i; \
259 } else { \
260 _ri_ptr[_ri_idx + _i].res_inst_id = \
261 RES_INSTANCE_NOT_CREATED; \
262 } \
263 } \
264 } \
265 _ri_idx += _ri_count; \
266 } while (false)
267
268 #define _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create) \
269 do { \
270 if (_ri_count > 0) { \
271 for (int _i = 0; _i < _ri_count; _i++) { \
272 _ri_ptr[_ri_idx + _i].data_ptr = NULL; \
273 _ri_ptr[_ri_idx + _i].max_data_len = 0; \
274 _ri_ptr[_ri_idx + _i].data_len = 0; \
275 if (_ri_create) { \
276 _ri_ptr[_ri_idx + _i].res_inst_id = \
277 _i; \
278 } else { \
279 _ri_ptr[_ri_idx + _i].res_inst_id = \
280 RES_INSTANCE_NOT_CREATED; \
281 } \
282 } \
283 } \
284 _ri_idx += _ri_count; \
285 } while (false)
286
287 #define INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
288 _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
289 _data_ptr, _data_len, \
290 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
291 do { \
292 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
293 (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
294 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
295 _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
296 _data_ptr, _data_len, _data_len); \
297 ++_r_idx; \
298 } while (false)
299
300 #define INIT_OBJ_RES_LEN(_id, _r_ptr, _r_idx, \
301 _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
302 _data_ptr, _data_sz, _data_len, \
303 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
304 do { \
305 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
306 (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
307 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
308 _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
309 _data_ptr, _data_sz, _data_len); \
310 ++_r_idx; \
311 } while (false)
312
313 #define INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
314 _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
315 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
316 do { \
317 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
318 (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
319 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
320 _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create); \
321 ++_r_idx; \
322 } while (false)
323
324 #define INIT_OBJ_RES_MULTI_DATA(_id, _r_ptr, _r_idx, \
325 _ri_ptr, _ri_idx, _ri_count, _ri_create, \
326 _data_ptr, _data_len) \
327 INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
328 _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
329 _data_ptr, _data_len, NULL, NULL, NULL, NULL, NULL)
330
331 #define INIT_OBJ_RES_MULTI_DATA_LEN(_id, _r_ptr, _r_idx, \
332 _ri_ptr, _ri_idx, _ri_count, _ri_create, \
333 _data_ptr, _data_sz, _data_len) \
334 INIT_OBJ_RES_LEN(_id, _r_ptr, _r_idx, \
335 _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
336 _data_ptr, _data_sz, _data_len, NULL, NULL, NULL, NULL, NULL)
337
338 #define INIT_OBJ_RES_MULTI_OPTDATA(_id, _r_ptr, _r_idx, \
339 _ri_ptr, _ri_idx, _ri_count, _ri_create) \
340 INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
341 _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
342 NULL, NULL, NULL, NULL, NULL)
343
344 #define INIT_OBJ_RES_DATA_LEN(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, \
345 _data_ptr, _data_sz, _data_len) \
346 INIT_OBJ_RES_LEN(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, false, true, \
347 _data_ptr, _data_sz, _data_len, NULL, NULL, NULL, NULL, NULL)
348
349 #define INIT_OBJ_RES_DATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, _data_ptr, _data_len) \
350 INIT_OBJ_RES_DATA_LEN(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, _data_ptr, _data_len, \
351 _data_len)
352
353 #define INIT_OBJ_RES_OPTDATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx) \
354 INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, false, \
355 true, NULL, NULL, NULL, NULL, NULL)
356
357 #define INIT_OBJ_RES_EXECUTE(_id, _r_ptr, _r_idx, _ex_cb) \
358 do { \
359 _INIT_OBJ_RES(_id, _r_ptr, _r_idx, NULL, 0, false, \
360 NULL, NULL, NULL, NULL, _ex_cb); \
361 ++_r_idx; \
362 } while (false)
363
364
365 #define LWM2M_ATTR_PMIN 0
366 #define LWM2M_ATTR_PMAX 1
367 #define LWM2M_ATTR_GT 2
368 #define LWM2M_ATTR_LT 3
369 #define LWM2M_ATTR_STEP 4
370 #define NR_LWM2M_ATTR 5
371
372 /* TODO: support multiple server (sec 5.4.2) */
373 struct lwm2m_attr {
374 void *ref;
375
376 /* values */
377 union {
378 double float_val;
379 int32_t int_val;
380 };
381
382 uint8_t type;
383 };
384
385 struct lwm2m_engine_res_inst {
386 void *data_ptr;
387 uint16_t max_data_len;
388 uint16_t data_len;
389 uint16_t res_inst_id; /* 65535 == not "created" */
390 uint8_t data_flags;
391 };
392
393 struct lwm2m_engine_res {
394 lwm2m_engine_get_data_cb_t read_cb;
395 lwm2m_engine_get_data_cb_t pre_write_cb;
396 #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0
397 lwm2m_engine_set_data_cb_t validate_cb;
398 #endif
399 lwm2m_engine_set_data_cb_t post_write_cb;
400 lwm2m_engine_execute_cb_t execute_cb;
401
402 struct lwm2m_engine_res_inst *res_instances;
403 uint16_t res_id;
404 uint8_t res_inst_count;
405 bool multi_res_inst;
406 };
407
408 struct lwm2m_engine_obj_inst {
409 /* instance list */
410 sys_snode_t node;
411
412 struct lwm2m_engine_obj *obj;
413 struct lwm2m_engine_res *resources;
414
415 /* object instance member data */
416 uint16_t obj_inst_id;
417 uint16_t resource_count;
418 };
419
420 /* Initialize resource instances prior to use */
init_res_instance(struct lwm2m_engine_res_inst * ri,size_t ri_len)421 static inline void init_res_instance(struct lwm2m_engine_res_inst *ri,
422 size_t ri_len)
423 {
424 size_t i;
425
426 memset(ri, 0, sizeof(*ri) * ri_len);
427 for (i = 0; i < ri_len; i++) {
428 ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED;
429 }
430 }
431
432 struct lwm2m_opaque_context {
433 size_t len;
434 size_t offset;
435 };
436
437 struct lwm2m_block_context {
438 struct coap_block_context ctx;
439 struct lwm2m_opaque_context opaque;
440 int64_t timestamp;
441 uint32_t expected;
442 bool last_block : 1;
443 struct lwm2m_obj_path path;
444 };
445
446 struct lwm2m_output_context {
447 const struct lwm2m_writer *writer;
448 struct coap_packet *out_cpkt;
449
450 #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER)
451 /* Corresponding block context. NULL if block transfer is not used. */
452 struct coap_block_context *block_ctx;
453 #endif
454
455 /* private output data */
456 void *user_data;
457 };
458
459 struct lwm2m_input_context {
460 const struct lwm2m_reader *reader;
461 struct coap_packet *in_cpkt;
462
463 /* current position in buffer */
464 uint16_t offset;
465
466 /* Corresponding block context. NULL if block transfer is not used. */
467 struct lwm2m_block_context *block_ctx;
468
469 /* private output data */
470 void *user_data;
471 };
472
473 /* Establish a message timeout callback */
474 typedef void (*lwm2m_message_timeout_cb_t)(struct lwm2m_message *msg);
475
476 /* Internal LwM2M message structure to track in-flight messages. */
477 struct lwm2m_message {
478 sys_snode_t node;
479
480 /** LwM2M context related to this message */
481 struct lwm2m_ctx *ctx;
482
483 /** Incoming / outgoing contexts */
484 struct lwm2m_input_context in;
485 struct lwm2m_output_context out;
486
487 /** Incoming path */
488 struct lwm2m_obj_path path;
489
490 /** CoAP packet data related to the outgoing message */
491 struct coap_packet cpkt;
492
493 /** Buffer data related outgoing message */
494 uint8_t msg_data[CONFIG_LWM2M_COAP_MAX_MSG_SIZE];
495
496 #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER)
497 /** Buffer data containing complete message */
498 struct coap_packet body_encode_buffer;
499 #endif
500
501 /** Message transmission handling for TYPE_CON */
502 struct coap_pending *pending;
503 struct coap_reply *reply;
504 #if defined(CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT)
505 struct lwm2m_cache_read_info *cache_info;
506 #endif
507
508 /** Message configuration */
509 uint8_t *token;
510 coap_reply_t reply_cb;
511 lwm2m_message_timeout_cb_t message_timeout_cb;
512 lwm2m_send_cb_t send_status_cb;
513 uint16_t mid;
514 uint8_t type;
515 uint8_t code;
516 uint8_t tkl;
517
518 /** Incoming message action */
519 uint8_t operation;
520
521 /** Information whether the message was acknowledged. */
522 bool acknowledged : 1;
523
524 /** Indicate that this is part of outgoing block transfer. */
525 bool block_send : 1;
526 };
527
528 /* LWM2M format writer for the various formats supported */
529 struct lwm2m_writer {
530 int (*put_begin)(struct lwm2m_output_context *out,
531 struct lwm2m_obj_path *path);
532 int (*put_end)(struct lwm2m_output_context *out,
533 struct lwm2m_obj_path *path);
534 int (*put_begin_oi)(struct lwm2m_output_context *out,
535 struct lwm2m_obj_path *path);
536 int (*put_end_oi)(struct lwm2m_output_context *out,
537 struct lwm2m_obj_path *path);
538 int (*put_begin_r)(struct lwm2m_output_context *out,
539 struct lwm2m_obj_path *path);
540 int (*put_end_r)(struct lwm2m_output_context *out,
541 struct lwm2m_obj_path *path);
542 int (*put_begin_ri)(struct lwm2m_output_context *out,
543 struct lwm2m_obj_path *path);
544 int (*put_end_ri)(struct lwm2m_output_context *out,
545 struct lwm2m_obj_path *path);
546 int (*put_data_timestamp)(struct lwm2m_output_context *out,
547 time_t value);
548 int (*put_s8)(struct lwm2m_output_context *out,
549 struct lwm2m_obj_path *path, int8_t value);
550 int (*put_s16)(struct lwm2m_output_context *out,
551 struct lwm2m_obj_path *path, int16_t value);
552 int (*put_s32)(struct lwm2m_output_context *out,
553 struct lwm2m_obj_path *path, int32_t value);
554 int (*put_s64)(struct lwm2m_output_context *out,
555 struct lwm2m_obj_path *path, int64_t value);
556 int (*put_time)(struct lwm2m_output_context *out,
557 struct lwm2m_obj_path *path, time_t value);
558 int (*put_string)(struct lwm2m_output_context *out,
559 struct lwm2m_obj_path *path, char *buf,
560 size_t buflen);
561 int (*put_float)(struct lwm2m_output_context *out,
562 struct lwm2m_obj_path *path, double *value);
563 int (*put_bool)(struct lwm2m_output_context *out,
564 struct lwm2m_obj_path *path, bool value);
565 int (*put_opaque)(struct lwm2m_output_context *out,
566 struct lwm2m_obj_path *path, char *buf,
567 size_t buflen);
568 int (*put_objlnk)(struct lwm2m_output_context *out,
569 struct lwm2m_obj_path *path,
570 struct lwm2m_objlnk *value);
571 int (*put_corelink)(struct lwm2m_output_context *out,
572 const struct lwm2m_obj_path *path);
573 };
574
575 struct lwm2m_reader {
576 int (*get_s32)(struct lwm2m_input_context *in, int32_t *value);
577 int (*get_s64)(struct lwm2m_input_context *in, int64_t *value);
578 int (*get_time)(struct lwm2m_input_context *in, time_t *value);
579 int (*get_string)(struct lwm2m_input_context *in, uint8_t *buf,
580 size_t buflen);
581 int (*get_float)(struct lwm2m_input_context *in, double *value);
582 int (*get_bool)(struct lwm2m_input_context *in, bool *value);
583 int (*get_opaque)(struct lwm2m_input_context *in, uint8_t *buf,
584 size_t buflen, struct lwm2m_opaque_context *opaque,
585 bool *last_block);
586 int (*get_objlnk)(struct lwm2m_input_context *in,
587 struct lwm2m_objlnk *value);
588 };
589
590 /* output user_data management functions */
591
engine_set_out_user_data(struct lwm2m_output_context * out,void * user_data)592 static inline void engine_set_out_user_data(struct lwm2m_output_context *out,
593 void *user_data)
594 {
595 out->user_data = user_data;
596 }
597
engine_get_out_user_data(struct lwm2m_output_context * out)598 static inline void *engine_get_out_user_data(struct lwm2m_output_context *out)
599 {
600 return out->user_data;
601 }
602
603 static inline void
engine_clear_out_user_data(struct lwm2m_output_context * out)604 engine_clear_out_user_data(struct lwm2m_output_context *out)
605 {
606 out->user_data = NULL;
607 }
608
engine_set_in_user_data(struct lwm2m_input_context * in,void * user_data)609 static inline void engine_set_in_user_data(struct lwm2m_input_context *in,
610 void *user_data)
611 {
612 in->user_data = user_data;
613 }
614
engine_get_in_user_data(struct lwm2m_input_context * in)615 static inline void *engine_get_in_user_data(struct lwm2m_input_context *in)
616 {
617 return in->user_data;
618 }
619
620 static inline void
engine_clear_in_user_data(struct lwm2m_input_context * in)621 engine_clear_in_user_data(struct lwm2m_input_context *in)
622 {
623 in->user_data = NULL;
624 }
625
626 /* inline multi-format write / read functions */
627
engine_put_begin(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)628 static inline int engine_put_begin(struct lwm2m_output_context *out,
629 struct lwm2m_obj_path *path)
630 {
631 if (out->writer->put_begin) {
632 return out->writer->put_begin(out, path);
633 }
634
635 return 0;
636 }
637
engine_put_end(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)638 static inline int engine_put_end(struct lwm2m_output_context *out,
639 struct lwm2m_obj_path *path)
640 {
641 if (out->writer->put_end) {
642 return out->writer->put_end(out, path);
643 }
644
645 return 0;
646 }
647
engine_put_begin_oi(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)648 static inline int engine_put_begin_oi(struct lwm2m_output_context *out,
649 struct lwm2m_obj_path *path)
650 {
651 if (out->writer->put_begin_oi) {
652 return out->writer->put_begin_oi(out, path);
653 }
654
655 return 0;
656 }
657
engine_put_end_oi(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)658 static inline int engine_put_end_oi(struct lwm2m_output_context *out,
659 struct lwm2m_obj_path *path)
660 {
661 if (out->writer->put_end_oi) {
662 return out->writer->put_end_oi(out, path);
663 }
664
665 return 0;
666 }
667
engine_put_begin_r(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)668 static inline int engine_put_begin_r(struct lwm2m_output_context *out,
669 struct lwm2m_obj_path *path)
670 {
671 if (out->writer->put_begin_r) {
672 return out->writer->put_begin_r(out, path);
673 }
674
675 return 0;
676 }
677
engine_put_end_r(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)678 static inline int engine_put_end_r(struct lwm2m_output_context *out,
679 struct lwm2m_obj_path *path)
680 {
681 if (out->writer->put_end_r) {
682 return out->writer->put_end_r(out, path);
683 }
684
685 return 0;
686 }
687
engine_put_begin_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)688 static inline int engine_put_begin_ri(struct lwm2m_output_context *out,
689 struct lwm2m_obj_path *path)
690 {
691 if (out->writer->put_begin_ri) {
692 return out->writer->put_begin_ri(out, path);
693 }
694
695 return 0;
696 }
697
engine_put_end_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)698 static inline int engine_put_end_ri(struct lwm2m_output_context *out,
699 struct lwm2m_obj_path *path)
700 {
701 if (out->writer->put_end_ri) {
702 return out->writer->put_end_ri(out, path);
703 }
704
705 return 0;
706 }
707
engine_put_s8(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int8_t value)708 static inline int engine_put_s8(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
709 int8_t value)
710 {
711 if (out->writer->put_s8) {
712 return out->writer->put_s8(out, path, value);
713 }
714 return -ENOTSUP;
715 }
716
engine_put_s16(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int16_t value)717 static inline int engine_put_s16(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
718 int16_t value)
719 {
720 if (out->writer->put_s16) {
721 return out->writer->put_s16(out, path, value);
722 }
723 return -ENOTSUP;
724 }
725
engine_put_s32(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int32_t value)726 static inline int engine_put_s32(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
727 int32_t value)
728 {
729 if (out->writer->put_s32) {
730 return out->writer->put_s32(out, path, value);
731 }
732 return -ENOTSUP;
733 }
734
engine_put_s64(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int64_t value)735 static inline int engine_put_s64(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
736 int64_t value)
737 {
738 if (out->writer->put_s64) {
739 return out->writer->put_s64(out, path, value);
740 }
741 return -ENOTSUP;
742 }
743
engine_put_string(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)744 static inline int engine_put_string(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
745 char *buf, size_t buflen)
746 {
747 if (out->writer->put_string) {
748 return out->writer->put_string(out, path, buf, buflen);
749 }
750 return -ENOTSUP;
751 }
752
engine_put_float(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,double * value)753 static inline int engine_put_float(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
754 double *value)
755 {
756 if (out->writer->put_float) {
757 return out->writer->put_float(out, path, value);
758 }
759 return -ENOTSUP;
760 }
761
engine_put_time(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,time_t value)762 static inline int engine_put_time(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
763 time_t value)
764 {
765 if (out->writer->put_time) {
766 return out->writer->put_time(out, path, value);
767 }
768 return -ENOTSUP;
769 }
770
engine_put_bool(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,bool value)771 static inline int engine_put_bool(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
772 bool value)
773 {
774 if (out->writer->put_bool) {
775 return out->writer->put_bool(out, path, value);
776 }
777 return -ENOTSUP;
778 }
779
engine_put_opaque(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)780 static inline int engine_put_opaque(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
781 char *buf, size_t buflen)
782 {
783 if (out->writer->put_opaque) {
784 return out->writer->put_opaque(out, path, buf, buflen);
785 }
786
787 return -ENOTSUP;
788 }
789
engine_put_objlnk(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,struct lwm2m_objlnk * value)790 static inline int engine_put_objlnk(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
791 struct lwm2m_objlnk *value)
792 {
793 if (out->writer->put_objlnk) {
794 return out->writer->put_objlnk(out, path, value);
795 }
796 return -ENOTSUP;
797 }
798
engine_put_corelink(struct lwm2m_output_context * out,const struct lwm2m_obj_path * path)799 static inline int engine_put_corelink(struct lwm2m_output_context *out,
800 const struct lwm2m_obj_path *path)
801 {
802 if (out->writer->put_corelink) {
803 return out->writer->put_corelink(out, path);
804 }
805
806 return -ENOTSUP;
807 }
808
engine_put_timestamp(struct lwm2m_output_context * out,time_t timestamp)809 static inline int engine_put_timestamp(struct lwm2m_output_context *out, time_t timestamp)
810 {
811 if (out->writer->put_data_timestamp) {
812 return out->writer->put_data_timestamp(out, timestamp);
813 }
814
815 return -ENOTSUP;
816 }
817
engine_get_s32(struct lwm2m_input_context * in,int32_t * value)818 static inline int engine_get_s32(struct lwm2m_input_context *in, int32_t *value)
819 {
820 if (in->reader->get_s32) {
821 return in->reader->get_s32(in, value);
822 }
823 return -ENOTSUP;
824 }
825
engine_get_s64(struct lwm2m_input_context * in,int64_t * value)826 static inline int engine_get_s64(struct lwm2m_input_context *in, int64_t *value)
827 {
828 if (in->reader->get_s64) {
829 return in->reader->get_s64(in, value);
830 }
831 return -ENOTSUP;
832 }
833
engine_get_string(struct lwm2m_input_context * in,uint8_t * buf,size_t buflen)834 static inline int engine_get_string(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen)
835 {
836 if (in->reader->get_string) {
837 return in->reader->get_string(in, buf, buflen);
838 }
839 return -ENOTSUP;
840 }
841
engine_get_time(struct lwm2m_input_context * in,time_t * value)842 static inline int engine_get_time(struct lwm2m_input_context *in, time_t *value)
843 {
844 if (in->reader->get_time) {
845 return in->reader->get_time(in, value);
846 }
847 return -ENOTSUP;
848 }
849
engine_get_float(struct lwm2m_input_context * in,double * value)850 static inline int engine_get_float(struct lwm2m_input_context *in, double *value)
851 {
852 if (in->reader->get_float) {
853 return in->reader->get_float(in, value);
854 }
855 return -ENOTSUP;
856 }
857
engine_get_bool(struct lwm2m_input_context * in,bool * value)858 static inline int engine_get_bool(struct lwm2m_input_context *in, bool *value)
859 {
860 if (in->reader->get_bool) {
861 return in->reader->get_bool(in, value);
862 }
863 return -ENOTSUP;
864 }
865
engine_get_opaque(struct lwm2m_input_context * in,uint8_t * buf,size_t buflen,struct lwm2m_opaque_context * opaque,bool * last_block)866 static inline int engine_get_opaque(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen,
867 struct lwm2m_opaque_context *opaque, bool *last_block)
868 {
869 if (in->reader->get_opaque) {
870 return in->reader->get_opaque(in, buf, buflen, opaque, last_block);
871 }
872
873 return -ENOTSUP;
874 }
875
engine_get_objlnk(struct lwm2m_input_context * in,struct lwm2m_objlnk * value)876 static inline int engine_get_objlnk(struct lwm2m_input_context *in, struct lwm2m_objlnk *value)
877 {
878 if (in->reader->get_objlnk) {
879 return in->reader->get_objlnk(in, value);
880 }
881 return -ENOTSUP;
882 }
883
884 #endif /* LWM2M_OBJECT_H_ */
885