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 <kernel.h>
51 
52 #include <net/net_ip.h>
53 #include <sys/printk.h>
54 #include <sys/util.h>
55 #include <sys/types.h>
56 
57 #include <net/coap.h>
58 #include <net/lwm2m.h>
59 
60 #include "buf_util.h"
61 
62 /* #####/###/#####/### + NULL */
63 #define MAX_RESOURCE_LEN	20
64 
65 /* operations / permissions */
66 /* values from 0 to 7 can be used as permission checks */
67 #define LWM2M_OP_READ		0
68 #define LWM2M_OP_WRITE		1
69 #define LWM2M_OP_CREATE		2
70 #define LWM2M_OP_DELETE		3
71 #define LWM2M_OP_EXECUTE	4
72 #define LWM2M_FLAG_OPTIONAL	7
73 /* values >7 aren't used for permission checks */
74 #define LWM2M_OP_DISCOVER	8
75 #define LWM2M_OP_WRITE_ATTR	9
76 
77 /* resource permissions */
78 #define LWM2M_PERM_R		BIT(LWM2M_OP_READ)
79 #define LWM2M_PERM_R_OPT	(BIT(LWM2M_OP_READ) | \
80 				 BIT(LWM2M_FLAG_OPTIONAL))
81 #define LWM2M_PERM_W		(BIT(LWM2M_OP_WRITE) | \
82 				 BIT(LWM2M_OP_CREATE))
83 #define LWM2M_PERM_W_OPT	(BIT(LWM2M_OP_WRITE) | \
84 				 BIT(LWM2M_OP_CREATE) | \
85 				 BIT(LWM2M_FLAG_OPTIONAL))
86 #define LWM2M_PERM_X		BIT(LWM2M_OP_EXECUTE)
87 #define LWM2M_PERM_X_OPT	(BIT(LWM2M_OP_EXECUTE) | \
88 				 BIT(LWM2M_FLAG_OPTIONAL))
89 #define LWM2M_PERM_RW		(BIT(LWM2M_OP_READ) | \
90 				 BIT(LWM2M_OP_WRITE) | \
91 				 BIT(LWM2M_OP_CREATE))
92 #define LWM2M_PERM_RW_OPT	(BIT(LWM2M_OP_READ) | \
93 				 BIT(LWM2M_OP_WRITE) | \
94 				 BIT(LWM2M_OP_CREATE) | \
95 				 BIT(LWM2M_FLAG_OPTIONAL))
96 #define LWM2M_PERM_RWX		(BIT(LWM2M_OP_READ) | \
97 				 BIT(LWM2M_OP_WRITE) | \
98 				 BIT(LWM2M_OP_CREATE) | \
99 				 BIT(LWM2M_OP_EXECUTE))
100 #define LWM2M_PERM_RWX_OPT	(BIT(LWM2M_OP_READ) | \
101 				 BIT(LWM2M_OP_WRITE) | \
102 				 BIT(LWM2M_OP_CREATE) | \
103 				 BIT(LWM2M_OP_EXECUTE) | \
104 				 BIT(LWM2M_FLAG_OPTIONAL))
105 
106 #define LWM2M_HAS_PERM(of, p)	(((of)->permissions & p) == p)
107 
108 /* resource types */
109 #define LWM2M_RES_TYPE_NONE	0
110 #define LWM2M_RES_TYPE_OPAQUE	1
111 #define LWM2M_RES_TYPE_STRING	2
112 #define LWM2M_RES_TYPE_UINT	3
113 #define LWM2M_RES_TYPE_U32	3
114 #define LWM2M_RES_TYPE_U16	4
115 #define LWM2M_RES_TYPE_U8	5
116 #define LWM2M_RES_TYPE_INT64	6
117 #define LWM2M_RES_TYPE_S64	6
118 #define LWM2M_RES_TYPE_INT	7
119 #define LWM2M_RES_TYPE_S32	7
120 #define LWM2M_RES_TYPE_S16	8
121 #define LWM2M_RES_TYPE_S8	9
122 #define LWM2M_RES_TYPE_BOOL	10
123 #define LWM2M_RES_TYPE_TIME	11
124 #define LWM2M_RES_TYPE_FLOAT	12
125 #define LWM2M_RES_TYPE_OBJLNK	13
126 
127 /* remember that we have already output a value - can be between two block's */
128 #define WRITER_OUTPUT_VALUE      1
129 #define WRITER_RESOURCE_INSTANCE 2
130 
131 #define MAX_PACKET_SIZE		(CONFIG_LWM2M_COAP_BLOCK_SIZE + \
132 				 CONFIG_LWM2M_ENGINE_MESSAGE_HEADER_SIZE)
133 
134 /* buffer util macros */
135 #define CPKT_BUF_WRITE(cpkt)	(cpkt)->data, &(cpkt)->offset, (cpkt)->max_len
136 #define CPKT_BUF_READ(cpkt)	(cpkt)->data, (cpkt)->max_len
137 
138 struct lwm2m_engine_obj;
139 struct lwm2m_message;
140 
141 #define LWM2M_PATH_LEVEL_NONE 0
142 #define LWM2M_PATH_LEVEL_OBJECT 1
143 #define LWM2M_PATH_LEVEL_OBJECT_INST 2
144 #define LWM2M_PATH_LEVEL_RESOURCE 3
145 #define LWM2M_PATH_LEVEL_RESOURCE_INST 4
146 
147 /* path representing object instances */
148 struct lwm2m_obj_path {
149 	uint16_t obj_id;
150 	uint16_t obj_inst_id;
151 	uint16_t res_id;
152 	uint16_t res_inst_id;
153 	uint8_t  level;  /* 0/1/2/3/4 (4 = resource instance) */
154 };
155 
156 #define OBJ_FIELD(_id, _perm, _type) \
157 	{ .res_id = _id, \
158 	  .permissions = LWM2M_PERM_ ## _perm, \
159 	  .data_type = LWM2M_RES_TYPE_ ## _type, }
160 
161 /* Keep OBJ_FIELD_DATA around for historical reasons */
162 #define OBJ_FIELD_DATA(res_id, perm, type) \
163 	OBJ_FIELD(res_id, perm, type)
164 
165 #define OBJ_FIELD_EXECUTE(res_id) \
166 	OBJ_FIELD(res_id, X, NONE)
167 
168 #define OBJ_FIELD_EXECUTE_OPT(res_id) \
169 	OBJ_FIELD(res_id, X_OPT, NONE)
170 
171 struct lwm2m_engine_obj_field {
172 	uint16_t  res_id;
173 	uint8_t   permissions;
174 	uint8_t   data_type;
175 };
176 
177 typedef struct lwm2m_engine_obj_inst *
178 	(*lwm2m_engine_obj_create_cb_t)(uint16_t obj_inst_id);
179 
180 struct lwm2m_engine_obj {
181 	/* object list */
182 	sys_snode_t node;
183 
184 	/* object field definitions */
185 	struct lwm2m_engine_obj_field *fields;
186 
187 	/* object event callbacks */
188 	lwm2m_engine_obj_create_cb_t create_cb;
189 	lwm2m_engine_user_cb_t delete_cb;
190 	lwm2m_engine_user_cb_t user_create_cb;
191 	lwm2m_engine_user_cb_t user_delete_cb;
192 
193 	/* object member data */
194 	uint16_t obj_id;
195 	uint16_t field_count;
196 	uint16_t instance_count;
197 	uint16_t max_instance_count;
198 
199 	/* Object version information. */
200 	uint8_t version_major;
201 	uint8_t version_minor;
202 
203 	/* Object is a core object (defined in the official LwM2M spec.) */
204 	bool is_core : 1;
205 };
206 
207 /* Resource instances with this value are considered "not created" yet */
208 #define RES_INSTANCE_NOT_CREATED 65535
209 
210 /* Resource macros */
211 
212 #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0
213 #define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, _multi_ri, \
214 		      _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
215 	_r_ptr[_r_idx].res_id = _id; \
216 	_r_ptr[_r_idx].res_instances = _ri_ptr; \
217 	_r_ptr[_r_idx].res_inst_count = _ri_count; \
218 	_r_ptr[_r_idx].multi_res_inst = _multi_ri; \
219 	_r_ptr[_r_idx].read_cb = _r_cb; \
220 	_r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
221 	_r_ptr[_r_idx].validate_cb = _val_cb; \
222 	_r_ptr[_r_idx].post_write_cb = _post_w_cb; \
223 	_r_ptr[_r_idx].execute_cb = _ex_cb
224 #else
225 #define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, _multi_ri, \
226 		      _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
227 	_r_ptr[_r_idx].res_id = _id; \
228 	_r_ptr[_r_idx].res_instances = _ri_ptr; \
229 	_r_ptr[_r_idx].res_inst_count = _ri_count; \
230 	_r_ptr[_r_idx].multi_res_inst = _multi_ri; \
231 	_r_ptr[_r_idx].read_cb = _r_cb; \
232 	_r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
233 	_r_ptr[_r_idx].post_write_cb = _post_w_cb; \
234 	_r_ptr[_r_idx].execute_cb = _ex_cb
235 #endif /* CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 */
236 
237 #define _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
238 			   _data_ptr, _data_len) \
239 	do { \
240 		if (_ri_ptr != NULL && _ri_count > 0) { \
241 			for (int _i = 0; _i < _ri_count; _i++) { \
242 				_ri_ptr[_ri_idx + _i].data_ptr = \
243 						(_data_ptr + _i); \
244 				_ri_ptr[_ri_idx + _i].max_data_len = \
245 						_data_len; \
246 				_ri_ptr[_ri_idx + _i].data_len = \
247 						_data_len; \
248 				if (_ri_create) { \
249 					_ri_ptr[_ri_idx + _i].res_inst_id = \
250 						_i; \
251 				} else { \
252 					_ri_ptr[_ri_idx + _i].res_inst_id = \
253 						RES_INSTANCE_NOT_CREATED; \
254 				} \
255 			} \
256 		} \
257 		_ri_idx += _ri_count; \
258 	} while (false)
259 
260 #define _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create) \
261 	do { \
262 		if (_ri_count > 0) { \
263 			for (int _i = 0; _i < _ri_count; _i++) { \
264 				_ri_ptr[_ri_idx + _i].data_ptr = NULL; \
265 				_ri_ptr[_ri_idx + _i].max_data_len = 0; \
266 				_ri_ptr[_ri_idx + _i].data_len = 0; \
267 				if (_ri_create) { \
268 					_ri_ptr[_ri_idx + _i].res_inst_id = \
269 						_i; \
270 				} else { \
271 					_ri_ptr[_ri_idx + _i].res_inst_id = \
272 						RES_INSTANCE_NOT_CREATED; \
273 				} \
274 			} \
275 		} \
276 		_ri_idx += _ri_count; \
277 	} while (false)
278 
279 #define INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
280 		     _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
281 		     _data_ptr, _data_len, \
282 		     _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
283 	do { \
284 		_INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
285 			      (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
286 			      _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
287 		_INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
288 				   _data_ptr, _data_len); \
289 	++_r_idx; \
290 	} while (false)
291 
292 
293 #define INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
294 			 _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \
295 			 _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \
296 	do { \
297 		_INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
298 			      (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \
299 			      _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \
300 		_INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create); \
301 		++_r_idx; \
302 	} while (false)
303 
304 #define INIT_OBJ_RES_MULTI_DATA(_id, _r_ptr, _r_idx, \
305 				_ri_ptr, _ri_idx, _ri_count, _ri_create, \
306 				_data_ptr, _data_len) \
307 	INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
308 		     _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
309 		     _data_ptr, _data_len, NULL, NULL, NULL, NULL, NULL)
310 
311 #define INIT_OBJ_RES_MULTI_OPTDATA(_id, _r_ptr, _r_idx, \
312 				   _ri_ptr, _ri_idx, _ri_count, _ri_create) \
313 	INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
314 			 _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \
315 			 NULL, NULL, NULL, NULL, NULL)
316 
317 #define INIT_OBJ_RES_DATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, \
318 			  _data_ptr, _data_len) \
319 	INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, false, true, \
320 		     _data_ptr, _data_len, NULL, NULL, NULL, NULL, NULL)
321 
322 #define INIT_OBJ_RES_OPTDATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx) \
323 	INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, false, \
324 			 true, NULL, NULL, NULL, NULL, NULL)
325 
326 #define INIT_OBJ_RES_EXECUTE(_id, _r_ptr, _r_idx, _ex_cb) \
327 	do { \
328 		_INIT_OBJ_RES(_id, _r_ptr, _r_idx, NULL, 0, false, \
329 			      NULL, NULL, NULL, NULL, _ex_cb); \
330 		++_r_idx; \
331 	} while (false)
332 
333 
334 #define LWM2M_ATTR_PMIN	0
335 #define LWM2M_ATTR_PMAX	1
336 #define LWM2M_ATTR_GT	2
337 #define LWM2M_ATTR_LT	3
338 #define LWM2M_ATTR_STEP	4
339 #define NR_LWM2M_ATTR	5
340 
341 /* TODO: support multiple server (sec 5.4.2) */
342 struct lwm2m_attr {
343 	void *ref;
344 
345 	/* values */
346 	union {
347 		float32_value_t float_val;
348 		int32_t int_val;
349 	};
350 
351 	uint8_t type;
352 };
353 
354 struct lwm2m_engine_res_inst {
355 	void  *data_ptr;
356 	uint16_t max_data_len;
357 	uint16_t data_len;
358 	uint16_t res_inst_id; /* 65535 == not "created" */
359 	uint8_t  data_flags;
360 };
361 
362 struct lwm2m_engine_res {
363 	lwm2m_engine_get_data_cb_t		read_cb;
364 	lwm2m_engine_get_data_cb_t		pre_write_cb;
365 #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0
366 	lwm2m_engine_set_data_cb_t		validate_cb;
367 #endif
368 	lwm2m_engine_set_data_cb_t		post_write_cb;
369 	lwm2m_engine_execute_cb_t		execute_cb;
370 
371 	struct lwm2m_engine_res_inst *res_instances;
372 	uint16_t res_id;
373 	uint8_t  res_inst_count;
374 	bool multi_res_inst;
375 };
376 
377 struct lwm2m_engine_obj_inst {
378 	/* instance list */
379 	sys_snode_t node;
380 
381 	struct lwm2m_engine_obj *obj;
382 	struct lwm2m_engine_res *resources;
383 
384 	/* object instance member data */
385 	uint16_t obj_inst_id;
386 	uint16_t resource_count;
387 };
388 
389 /* Initialize resource instances prior to use */
init_res_instance(struct lwm2m_engine_res_inst * ri,size_t ri_len)390 static inline void init_res_instance(struct lwm2m_engine_res_inst *ri,
391 				     size_t ri_len)
392 {
393 	size_t i;
394 
395 	memset(ri, 0, sizeof(*ri) * ri_len);
396 	for (i = 0; i < ri_len; i++) {
397 		ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED;
398 	}
399 }
400 
401 struct lwm2m_opaque_context {
402 	size_t len;
403 	size_t remaining;
404 };
405 
406 struct lwm2m_block_context {
407 	struct coap_block_context ctx;
408 	struct lwm2m_opaque_context opaque;
409 	int64_t timestamp;
410 	uint32_t expected;
411 	uint8_t token[8];
412 	uint8_t tkl;
413 	bool last_block : 1;
414 	uint16_t res_id;
415 };
416 
417 struct lwm2m_output_context {
418 	const struct lwm2m_writer *writer;
419 	struct coap_packet *out_cpkt;
420 
421 	/* private output data */
422 	void *user_data;
423 };
424 
425 struct lwm2m_input_context {
426 	const struct lwm2m_reader *reader;
427 	struct coap_packet *in_cpkt;
428 
429 	/* current position in buffer */
430 	uint16_t offset;
431 
432 	/* Corresponding block context. NULL if block transfer is not used. */
433 	struct lwm2m_block_context *block_ctx;
434 
435 	/* private output data */
436 	void *user_data;
437 };
438 
439 /* Establish a message timeout callback */
440 typedef void (*lwm2m_message_timeout_cb_t)(struct lwm2m_message *msg);
441 
442 /* Internal LwM2M message structure to track in-flight messages. */
443 struct lwm2m_message {
444 	sys_snode_t node;
445 
446 	/** LwM2M context related to this message */
447 	struct lwm2m_ctx *ctx;
448 
449 	/** Incoming / outgoing contexts */
450 	struct lwm2m_input_context in;
451 	struct lwm2m_output_context out;
452 
453 	/** Incoming path */
454 	struct lwm2m_obj_path path;
455 
456 	/** CoAP packet data related to the outgoing message */
457 	struct coap_packet cpkt;
458 
459 	/** Buffer data related outgoing message */
460 	uint8_t msg_data[MAX_PACKET_SIZE];
461 
462 	/** Message transmission handling for TYPE_CON */
463 	struct coap_pending *pending;
464 	struct coap_reply *reply;
465 
466 	/** Message configuration */
467 	uint8_t *token;
468 	coap_reply_t reply_cb;
469 	lwm2m_message_timeout_cb_t message_timeout_cb;
470 	uint16_t mid;
471 	uint8_t type;
472 	uint8_t code;
473 	uint8_t tkl;
474 
475 	/** Incoming message action */
476 	uint8_t operation;
477 
478 	/* Information whether the message was acknowledged. */
479 	bool acknowledged : 1;
480 };
481 
482 /* LWM2M format writer for the various formats supported */
483 struct lwm2m_writer {
484 	size_t (*put_begin)(struct lwm2m_output_context *out,
485 			    struct lwm2m_obj_path *path);
486 	size_t (*put_end)(struct lwm2m_output_context *out,
487 			  struct lwm2m_obj_path *path);
488 	size_t (*put_begin_oi)(struct lwm2m_output_context *out,
489 			       struct lwm2m_obj_path *path);
490 	size_t (*put_end_oi)(struct lwm2m_output_context *out,
491 			     struct lwm2m_obj_path *path);
492 	size_t (*put_begin_r)(struct lwm2m_output_context *out,
493 			      struct lwm2m_obj_path *path);
494 	size_t (*put_end_r)(struct lwm2m_output_context *out,
495 			    struct lwm2m_obj_path *path);
496 	size_t (*put_begin_ri)(struct lwm2m_output_context *out,
497 			       struct lwm2m_obj_path *path);
498 	size_t (*put_end_ri)(struct lwm2m_output_context *out,
499 			     struct lwm2m_obj_path *path);
500 	size_t (*put_s8)(struct lwm2m_output_context *out,
501 			 struct lwm2m_obj_path *path,
502 			 int8_t value);
503 	size_t (*put_s16)(struct lwm2m_output_context *out,
504 			  struct lwm2m_obj_path *path,
505 			  int16_t value);
506 	size_t (*put_s32)(struct lwm2m_output_context *out,
507 			  struct lwm2m_obj_path *path,
508 			  int32_t value);
509 	size_t (*put_s64)(struct lwm2m_output_context *out,
510 			  struct lwm2m_obj_path *path,
511 			  int64_t value);
512 	size_t (*put_string)(struct lwm2m_output_context *out,
513 			     struct lwm2m_obj_path *path,
514 			     char *buf, size_t buflen);
515 	size_t (*put_float32fix)(struct lwm2m_output_context *out,
516 				 struct lwm2m_obj_path *path,
517 				 float32_value_t *value);
518 	size_t (*put_bool)(struct lwm2m_output_context *out,
519 			   struct lwm2m_obj_path *path,
520 			   bool value);
521 	size_t (*put_opaque)(struct lwm2m_output_context *out,
522 			     struct lwm2m_obj_path *path,
523 			     char *buf, size_t buflen);
524 	size_t (*put_objlnk)(struct lwm2m_output_context *out,
525 			     struct lwm2m_obj_path *path,
526 			     struct lwm2m_objlnk *value);
527 	ssize_t (*put_corelink)(struct lwm2m_output_context *out,
528 				const struct lwm2m_obj_path *path);
529 };
530 
531 struct lwm2m_reader {
532 	size_t (*get_s32)(struct lwm2m_input_context *in,
533 			  int32_t *value);
534 	size_t (*get_s64)(struct lwm2m_input_context *in,
535 			  int64_t *value);
536 	size_t (*get_string)(struct lwm2m_input_context *in,
537 			     uint8_t *buf, size_t buflen);
538 	size_t (*get_float32fix)(struct lwm2m_input_context *in,
539 				 float32_value_t *value);
540 	size_t (*get_bool)(struct lwm2m_input_context *in,
541 			   bool *value);
542 	size_t (*get_opaque)(struct lwm2m_input_context *in,
543 			     uint8_t *buf, size_t buflen,
544 			     struct lwm2m_opaque_context *opaque,
545 			     bool *last_block);
546 	size_t (*get_objlnk)(struct lwm2m_input_context *in,
547 			     struct lwm2m_objlnk *value);
548 };
549 
550 /* output user_data management functions */
551 
engine_set_out_user_data(struct lwm2m_output_context * out,void * user_data)552 static inline void engine_set_out_user_data(struct lwm2m_output_context *out,
553 					    void *user_data)
554 {
555 	out->user_data = user_data;
556 }
557 
engine_get_out_user_data(struct lwm2m_output_context * out)558 static inline void *engine_get_out_user_data(struct lwm2m_output_context *out)
559 {
560 	return out->user_data;
561 }
562 
563 static inline void
engine_clear_out_user_data(struct lwm2m_output_context * out)564 engine_clear_out_user_data(struct lwm2m_output_context *out)
565 {
566 	out->user_data = NULL;
567 }
568 
engine_set_in_user_data(struct lwm2m_input_context * in,void * user_data)569 static inline void engine_set_in_user_data(struct lwm2m_input_context *in,
570 					   void *user_data)
571 {
572 	in->user_data = user_data;
573 }
574 
engine_get_in_user_data(struct lwm2m_input_context * in)575 static inline void *engine_get_in_user_data(struct lwm2m_input_context *in)
576 {
577 	return in->user_data;
578 }
579 
580 static inline void
engine_clear_in_user_data(struct lwm2m_input_context * in)581 engine_clear_in_user_data(struct lwm2m_input_context *in)
582 {
583 	in->user_data = NULL;
584 }
585 
586 /* inline multi-format write / read functions */
587 
engine_put_begin(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)588 static inline size_t engine_put_begin(struct lwm2m_output_context *out,
589 				      struct lwm2m_obj_path *path)
590 {
591 	if (out->writer->put_begin) {
592 		return out->writer->put_begin(out, path);
593 	}
594 
595 	return 0;
596 }
597 
engine_put_end(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)598 static inline size_t engine_put_end(struct lwm2m_output_context *out,
599 				    struct lwm2m_obj_path *path)
600 {
601 	if (out->writer->put_end) {
602 		return out->writer->put_end(out, path);
603 	}
604 
605 	return 0;
606 }
607 
engine_put_begin_oi(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)608 static inline size_t engine_put_begin_oi(struct lwm2m_output_context *out,
609 					 struct lwm2m_obj_path *path)
610 {
611 	if (out->writer->put_begin_oi) {
612 		return out->writer->put_begin_oi(out, path);
613 	}
614 
615 	return 0;
616 }
617 
engine_put_end_oi(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)618 static inline size_t engine_put_end_oi(struct lwm2m_output_context *out,
619 				       struct lwm2m_obj_path *path)
620 {
621 	if (out->writer->put_end_oi) {
622 		return out->writer->put_end_oi(out, path);
623 	}
624 
625 	return 0;
626 }
627 
engine_put_begin_r(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)628 static inline size_t engine_put_begin_r(struct lwm2m_output_context *out,
629 					struct lwm2m_obj_path *path)
630 {
631 	if (out->writer->put_begin_r) {
632 		return out->writer->put_begin_r(out, path);
633 	}
634 
635 	return 0;
636 }
637 
engine_put_end_r(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)638 static inline size_t engine_put_end_r(struct lwm2m_output_context *out,
639 				      struct lwm2m_obj_path *path)
640 {
641 	if (out->writer->put_end_r) {
642 		return out->writer->put_end_r(out, path);
643 	}
644 
645 	return 0;
646 }
647 
engine_put_begin_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)648 static inline size_t engine_put_begin_ri(struct lwm2m_output_context *out,
649 					 struct lwm2m_obj_path *path)
650 {
651 	if (out->writer->put_begin_ri) {
652 		return out->writer->put_begin_ri(out, path);
653 	}
654 
655 	return 0;
656 }
657 
engine_put_end_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)658 static inline size_t engine_put_end_ri(struct lwm2m_output_context *out,
659 				       struct lwm2m_obj_path *path)
660 {
661 	if (out->writer->put_end_ri) {
662 		return out->writer->put_end_ri(out, path);
663 	}
664 
665 	return 0;
666 }
667 
engine_put_s8(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int8_t value)668 static inline size_t engine_put_s8(struct lwm2m_output_context *out,
669 				   struct lwm2m_obj_path *path,
670 				   int8_t value)
671 {
672 	return out->writer->put_s8(out, path, value);
673 }
674 
engine_put_s16(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int16_t value)675 static inline size_t engine_put_s16(struct lwm2m_output_context *out,
676 				    struct lwm2m_obj_path *path,
677 				    int16_t value)
678 {
679 	return out->writer->put_s16(out, path, value);
680 }
681 
engine_put_s32(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int32_t value)682 static inline size_t engine_put_s32(struct lwm2m_output_context *out,
683 				    struct lwm2m_obj_path *path,
684 				    int32_t value)
685 {
686 	return out->writer->put_s32(out, path, value);
687 }
688 
engine_put_s64(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int64_t value)689 static inline size_t engine_put_s64(struct lwm2m_output_context *out,
690 				    struct lwm2m_obj_path *path,
691 				    int64_t value)
692 {
693 	return out->writer->put_s64(out, path, value);
694 }
695 
engine_put_string(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)696 static inline size_t engine_put_string(struct lwm2m_output_context *out,
697 				       struct lwm2m_obj_path *path,
698 				       char *buf, size_t buflen)
699 {
700 	return out->writer->put_string(out, path, buf, buflen);
701 }
702 
engine_put_float32fix(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,float32_value_t * value)703 static inline size_t engine_put_float32fix(struct lwm2m_output_context *out,
704 					   struct lwm2m_obj_path *path,
705 					   float32_value_t *value)
706 {
707 	return out->writer->put_float32fix(out, path, value);
708 }
709 
engine_put_bool(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,bool value)710 static inline size_t engine_put_bool(struct lwm2m_output_context *out,
711 				     struct lwm2m_obj_path *path,
712 				     bool value)
713 {
714 	return out->writer->put_bool(out, path, value);
715 }
716 
engine_put_opaque(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)717 static inline size_t engine_put_opaque(struct lwm2m_output_context *out,
718 				       struct lwm2m_obj_path *path,
719 				       char *buf, size_t buflen)
720 {
721 	if (out->writer->put_opaque) {
722 		return out->writer->put_opaque(out, path, buf, buflen);
723 	}
724 
725 	return 0;
726 }
727 
engine_put_objlnk(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,struct lwm2m_objlnk * value)728 static inline size_t engine_put_objlnk(struct lwm2m_output_context *out,
729 				       struct lwm2m_obj_path *path,
730 				       struct lwm2m_objlnk *value)
731 {
732 	return out->writer->put_objlnk(out, path, value);
733 }
734 
engine_put_corelink(struct lwm2m_output_context * out,const struct lwm2m_obj_path * path)735 static inline ssize_t engine_put_corelink(struct lwm2m_output_context *out,
736 					  const struct lwm2m_obj_path *path)
737 {
738 	if (out->writer->put_corelink) {
739 		return out->writer->put_corelink(out, path);
740 	}
741 
742 	return -ENOTSUP;
743 }
744 
engine_get_s32(struct lwm2m_input_context * in,int32_t * value)745 static inline size_t engine_get_s32(struct lwm2m_input_context *in,
746 				    int32_t *value)
747 {
748 	return in->reader->get_s32(in, value);
749 }
750 
engine_get_s64(struct lwm2m_input_context * in,int64_t * value)751 static inline size_t engine_get_s64(struct lwm2m_input_context *in,
752 				    int64_t *value)
753 {
754 	return in->reader->get_s64(in, value);
755 }
756 
engine_get_string(struct lwm2m_input_context * in,uint8_t * buf,size_t buflen)757 static inline size_t engine_get_string(struct lwm2m_input_context *in,
758 				       uint8_t *buf, size_t buflen)
759 {
760 	return in->reader->get_string(in, buf, buflen);
761 }
762 
engine_get_float32fix(struct lwm2m_input_context * in,float32_value_t * value)763 static inline size_t engine_get_float32fix(struct lwm2m_input_context *in,
764 					   float32_value_t *value)
765 {
766 	return in->reader->get_float32fix(in, value);
767 }
768 
engine_get_bool(struct lwm2m_input_context * in,bool * value)769 static inline size_t engine_get_bool(struct lwm2m_input_context *in,
770 				     bool *value)
771 {
772 	return in->reader->get_bool(in, value);
773 }
774 
engine_get_opaque(struct lwm2m_input_context * in,uint8_t * buf,size_t buflen,struct lwm2m_opaque_context * opaque,bool * last_block)775 static inline size_t engine_get_opaque(struct lwm2m_input_context *in,
776 				       uint8_t *buf, size_t buflen,
777 				       struct lwm2m_opaque_context *opaque,
778 				       bool *last_block)
779 {
780 	if (in->reader->get_opaque) {
781 		return in->reader->get_opaque(in, buf, buflen,
782 					      opaque, last_block);
783 	}
784 
785 	return 0;
786 }
787 
engine_get_objlnk(struct lwm2m_input_context * in,struct lwm2m_objlnk * value)788 static inline size_t engine_get_objlnk(struct lwm2m_input_context *in,
789 				       struct lwm2m_objlnk *value)
790 {
791 	return in->reader->get_objlnk(in, value);
792 }
793 
794 #endif /* LWM2M_OBJECT_H_ */
795