2017-07-25 11:04:16 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2017 Linaro Limited
|
2019-01-24 14:40:23 -08:00
|
|
|
* Copyright (c) 2018-2019 Foundries.io
|
2017-07-25 11:04:16 -07:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015, Yanzi Networks AB.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the copyright holder nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Original Authors:
|
|
|
|
* Joakim Eriksson <joakime@sics.se>
|
|
|
|
* Niclas Finne <nfi@sics.se>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef LWM2M_OBJECT_H_
|
|
|
|
#define LWM2M_OBJECT_H_
|
|
|
|
|
|
|
|
/* stdint conversions */
|
|
|
|
#include <zephyr/types.h>
|
|
|
|
#include <stddef.h>
|
2019-01-24 14:40:23 -08:00
|
|
|
#include <kernel.h>
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
#include <net/net_ip.h>
|
2019-06-26 10:33:49 -04:00
|
|
|
#include <sys/printk.h>
|
2019-06-26 10:33:55 -04:00
|
|
|
#include <sys/util.h>
|
2019-01-24 14:40:23 -08:00
|
|
|
|
2019-02-01 14:44:42 +02:00
|
|
|
#include <net/coap.h>
|
2019-01-24 14:40:23 -08:00
|
|
|
#include <net/lwm2m.h>
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 14:13:07 -08:00
|
|
|
#include "buf_util.h"
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* #####/###/#####/### + NULL */
|
|
|
|
#define MAX_RESOURCE_LEN 20
|
|
|
|
|
2018-04-30 15:42:55 -07:00
|
|
|
/* operations / permissions */
|
|
|
|
/* values from 0 to 7 can be used as permission checks */
|
|
|
|
#define LWM2M_OP_READ 0
|
|
|
|
#define LWM2M_OP_WRITE 1
|
|
|
|
#define LWM2M_OP_CREATE 2
|
|
|
|
#define LWM2M_OP_DELETE 3
|
|
|
|
#define LWM2M_OP_EXECUTE 4
|
2018-04-30 16:43:25 -07:00
|
|
|
#define LWM2M_FLAG_OPTIONAL 7
|
2018-04-30 15:42:55 -07:00
|
|
|
/* values >7 aren't used for permission checks */
|
|
|
|
#define LWM2M_OP_DISCOVER 8
|
|
|
|
#define LWM2M_OP_WRITE_ATTR 9
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
/* resource permissions */
|
2018-04-30 15:35:43 -07:00
|
|
|
#define LWM2M_PERM_R BIT(LWM2M_OP_READ)
|
2018-04-30 16:43:25 -07:00
|
|
|
#define LWM2M_PERM_R_OPT (BIT(LWM2M_OP_READ) | \
|
|
|
|
BIT(LWM2M_FLAG_OPTIONAL))
|
2018-04-30 15:35:43 -07:00
|
|
|
#define LWM2M_PERM_W (BIT(LWM2M_OP_WRITE) | \
|
|
|
|
BIT(LWM2M_OP_CREATE))
|
2018-04-30 16:43:25 -07:00
|
|
|
#define LWM2M_PERM_W_OPT (BIT(LWM2M_OP_WRITE) | \
|
|
|
|
BIT(LWM2M_OP_CREATE) | \
|
|
|
|
BIT(LWM2M_FLAG_OPTIONAL))
|
2018-04-30 15:35:43 -07:00
|
|
|
#define LWM2M_PERM_X BIT(LWM2M_OP_EXECUTE)
|
2018-04-30 16:43:25 -07:00
|
|
|
#define LWM2M_PERM_X_OPT (BIT(LWM2M_OP_EXECUTE) | \
|
|
|
|
BIT(LWM2M_FLAG_OPTIONAL))
|
2018-04-30 15:35:43 -07:00
|
|
|
#define LWM2M_PERM_RW (BIT(LWM2M_OP_READ) | \
|
|
|
|
BIT(LWM2M_OP_WRITE) | \
|
|
|
|
BIT(LWM2M_OP_CREATE))
|
2018-04-30 16:43:25 -07:00
|
|
|
#define LWM2M_PERM_RW_OPT (BIT(LWM2M_OP_READ) | \
|
|
|
|
BIT(LWM2M_OP_WRITE) | \
|
|
|
|
BIT(LWM2M_OP_CREATE) | \
|
|
|
|
BIT(LWM2M_FLAG_OPTIONAL))
|
2018-04-30 15:35:43 -07:00
|
|
|
#define LWM2M_PERM_RWX (BIT(LWM2M_OP_READ) | \
|
|
|
|
BIT(LWM2M_OP_WRITE) | \
|
|
|
|
BIT(LWM2M_OP_CREATE) | \
|
|
|
|
BIT(LWM2M_OP_EXECUTE))
|
2018-04-30 16:43:25 -07:00
|
|
|
#define LWM2M_PERM_RWX_OPT (BIT(LWM2M_OP_READ) | \
|
|
|
|
BIT(LWM2M_OP_WRITE) | \
|
|
|
|
BIT(LWM2M_OP_CREATE) | \
|
|
|
|
BIT(LWM2M_OP_EXECUTE) | \
|
|
|
|
BIT(LWM2M_FLAG_OPTIONAL))
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-02-21 00:46:27 -08:00
|
|
|
#define LWM2M_HAS_PERM(of, p) (((of)->permissions & p) == p)
|
2018-04-30 15:30:12 -07:00
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* resource types */
|
|
|
|
#define LWM2M_RES_TYPE_NONE 0
|
|
|
|
#define LWM2M_RES_TYPE_OPAQUE 1
|
|
|
|
#define LWM2M_RES_TYPE_STRING 2
|
|
|
|
#define LWM2M_RES_TYPE_UINT64 3
|
|
|
|
#define LWM2M_RES_TYPE_U64 3
|
|
|
|
#define LWM2M_RES_TYPE_UINT 4
|
|
|
|
#define LWM2M_RES_TYPE_U32 4
|
|
|
|
#define LWM2M_RES_TYPE_U16 5
|
|
|
|
#define LWM2M_RES_TYPE_U8 6
|
|
|
|
#define LWM2M_RES_TYPE_INT64 7
|
|
|
|
#define LWM2M_RES_TYPE_S64 7
|
|
|
|
#define LWM2M_RES_TYPE_INT 8
|
|
|
|
#define LWM2M_RES_TYPE_S32 8
|
|
|
|
#define LWM2M_RES_TYPE_S16 9
|
|
|
|
#define LWM2M_RES_TYPE_S8 10
|
|
|
|
#define LWM2M_RES_TYPE_BOOL 11
|
|
|
|
#define LWM2M_RES_TYPE_TIME 12
|
|
|
|
#define LWM2M_RES_TYPE_FLOAT32 13
|
|
|
|
#define LWM2M_RES_TYPE_FLOAT64 14
|
2020-05-19 12:37:02 +02:00
|
|
|
#define LWM2M_RES_TYPE_OBJLNK 15
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
/* remember that we have already output a value - can be between two block's */
|
|
|
|
#define WRITER_OUTPUT_VALUE 1
|
|
|
|
#define WRITER_RESOURCE_INSTANCE 2
|
|
|
|
|
2019-01-25 14:13:07 -08:00
|
|
|
#define MAX_PACKET_SIZE (CONFIG_LWM2M_COAP_BLOCK_SIZE + \
|
|
|
|
CONFIG_LWM2M_ENGINE_MESSAGE_HEADER_SIZE)
|
|
|
|
|
|
|
|
/* buffer util macros */
|
|
|
|
#define CPKT_BUF_WRITE(cpkt) (cpkt)->data, &(cpkt)->offset, (cpkt)->max_len
|
|
|
|
#define CPKT_BUF_READ(cpkt) (cpkt)->data, (cpkt)->max_len
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
struct lwm2m_engine_obj;
|
2019-01-24 14:40:23 -08:00
|
|
|
struct lwm2m_message;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
/* path representing object instances */
|
|
|
|
struct lwm2m_obj_path {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t obj_id;
|
|
|
|
uint16_t obj_inst_id;
|
|
|
|
uint16_t res_id;
|
|
|
|
uint16_t res_inst_id;
|
|
|
|
uint8_t level; /* 0/1/2/3/4 (4 = resource instance) */
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
2019-07-29 10:06:00 -07:00
|
|
|
#define OBJ_FIELD(_id, _perm, _type) \
|
|
|
|
{ .res_id = _id, \
|
|
|
|
.permissions = LWM2M_PERM_ ## _perm, \
|
|
|
|
.data_type = LWM2M_RES_TYPE_ ## _type, }
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-07-29 10:06:00 -07:00
|
|
|
/* Keep OBJ_FIELD_DATA around for historical reasons */
|
2017-07-07 11:04:03 -07:00
|
|
|
#define OBJ_FIELD_DATA(res_id, perm, type) \
|
2019-07-29 10:06:00 -07:00
|
|
|
OBJ_FIELD(res_id, perm, type)
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
#define OBJ_FIELD_EXECUTE(res_id) \
|
2019-07-29 10:06:00 -07:00
|
|
|
OBJ_FIELD(res_id, X, NONE)
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2018-04-30 16:43:25 -07:00
|
|
|
#define OBJ_FIELD_EXECUTE_OPT(res_id) \
|
2019-07-29 10:06:00 -07:00
|
|
|
OBJ_FIELD(res_id, X_OPT, NONE)
|
2018-04-30 16:43:25 -07:00
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
struct lwm2m_engine_obj_field {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t res_id;
|
|
|
|
uint8_t permissions;
|
|
|
|
uint8_t data_type;
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct lwm2m_engine_obj_inst *
|
2020-05-27 11:26:57 -05:00
|
|
|
(*lwm2m_engine_obj_create_cb_t)(uint16_t obj_inst_id);
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
struct lwm2m_engine_obj {
|
2018-05-07 13:33:48 -07:00
|
|
|
/* object list */
|
2017-07-07 11:04:03 -07:00
|
|
|
sys_snode_t node;
|
2018-05-07 13:33:48 -07:00
|
|
|
|
|
|
|
/* object field definitions */
|
2017-07-07 11:04:03 -07:00
|
|
|
struct lwm2m_engine_obj_field *fields;
|
2018-05-07 13:33:48 -07:00
|
|
|
|
|
|
|
/* object event callbacks */
|
2017-07-07 11:04:03 -07:00
|
|
|
lwm2m_engine_obj_create_cb_t create_cb;
|
2019-07-29 10:07:00 -07:00
|
|
|
lwm2m_engine_user_cb_t delete_cb;
|
2018-07-12 10:00:01 -07:00
|
|
|
lwm2m_engine_user_cb_t user_create_cb;
|
|
|
|
lwm2m_engine_user_cb_t user_delete_cb;
|
2017-11-24 18:47:00 +08:00
|
|
|
|
2018-05-07 13:33:48 -07:00
|
|
|
/* object member data */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t obj_id;
|
|
|
|
uint16_t field_count;
|
|
|
|
uint16_t instance_count;
|
|
|
|
uint16_t max_instance_count;
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
2019-07-29 10:09:00 -07:00
|
|
|
/* Resource instances with this value are considered "not created" yet */
|
|
|
|
#define RES_INSTANCE_NOT_CREATED 65535
|
|
|
|
|
|
|
|
/* Resource macros */
|
|
|
|
#define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, \
|
|
|
|
_r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \
|
|
|
|
_r_ptr[_r_idx].res_id = _id; \
|
|
|
|
_r_ptr[_r_idx].res_instances = _ri_ptr; \
|
|
|
|
_r_ptr[_r_idx].res_inst_count = _ri_count; \
|
|
|
|
_r_ptr[_r_idx].read_cb = _r_cb; \
|
|
|
|
_r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
|
|
|
|
_r_ptr[_r_idx].post_write_cb = _post_w_cb; \
|
|
|
|
_r_ptr[_r_idx].execute_cb = _ex_cb
|
|
|
|
|
|
|
|
#define _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
|
|
|
|
_data_ptr, _data_len) \
|
|
|
|
do { \
|
|
|
|
if (_ri_ptr != NULL && _ri_count > 0) { \
|
|
|
|
for (int _i = 0; _i < _ri_count; _i++) { \
|
|
|
|
_ri_ptr[_ri_idx + _i].data_ptr = \
|
|
|
|
(_data_ptr + _i); \
|
|
|
|
_ri_ptr[_ri_idx + _i].data_len = \
|
|
|
|
_data_len; \
|
|
|
|
if (_ri_create) { \
|
|
|
|
_ri_ptr[_ri_idx + _i].res_inst_id = \
|
|
|
|
_i; \
|
|
|
|
} else { \
|
|
|
|
_ri_ptr[_ri_idx + _i].res_inst_id = \
|
|
|
|
RES_INSTANCE_NOT_CREATED; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
_ri_idx += _ri_count; \
|
|
|
|
} while (false)
|
|
|
|
|
|
|
|
#define _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create) \
|
|
|
|
do { \
|
|
|
|
if (_ri_count > 0) { \
|
|
|
|
for (int _i = 0; _i < _ri_count; _i++) { \
|
|
|
|
_ri_ptr[_ri_idx + _i].data_ptr = NULL; \
|
|
|
|
_ri_ptr[_ri_idx + _i].data_len = 0; \
|
|
|
|
if (_ri_create) { \
|
|
|
|
_ri_ptr[_ri_idx + _i].res_inst_id = \
|
|
|
|
_i; \
|
|
|
|
} else { \
|
|
|
|
_ri_ptr[_ri_idx + _i].res_inst_id = \
|
|
|
|
RES_INSTANCE_NOT_CREATED; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
_ri_idx += _ri_count; \
|
|
|
|
} while (false)
|
|
|
|
|
|
|
|
#define INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
|
|
|
|
_ri_ptr, _ri_idx, _ri_count, _ri_create, \
|
|
|
|
_data_ptr, _data_len, \
|
|
|
|
_r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \
|
|
|
|
do { \
|
|
|
|
_INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
|
|
|
|
(_ri_ptr + _ri_idx), _ri_count, \
|
|
|
|
_r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \
|
|
|
|
_INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
|
|
|
|
_data_ptr, _data_len); \
|
|
|
|
++_r_idx; \
|
|
|
|
} while (false)
|
|
|
|
|
|
|
|
|
|
|
|
#define INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
|
|
|
|
_ri_ptr, _ri_idx, _ri_count, _ri_create, \
|
|
|
|
_r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \
|
|
|
|
do { \
|
|
|
|
_INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
|
|
|
|
(_ri_ptr + _ri_idx), _ri_count, \
|
|
|
|
_r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \
|
|
|
|
_INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create); \
|
|
|
|
++_r_idx; \
|
|
|
|
} while (false)
|
|
|
|
|
|
|
|
#define INIT_OBJ_RES_MULTI_DATA(_id, _r_ptr, _r_idx, \
|
|
|
|
_ri_ptr, _ri_idx, _ri_count, _ri_create, \
|
|
|
|
_data_ptr, _data_len) \
|
|
|
|
INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
|
|
|
|
_ri_ptr, _ri_idx, _ri_count, _ri_create, \
|
|
|
|
_data_ptr, _data_len, NULL, NULL, NULL, NULL)
|
|
|
|
|
|
|
|
#define INIT_OBJ_RES_MULTI_OPTDATA(_id, _r_ptr, _r_idx, \
|
|
|
|
_ri_ptr, _ri_idx, _ri_count, _ri_create) \
|
|
|
|
INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
|
|
|
|
_ri_ptr, _ri_idx, _ri_count, _ri_create, \
|
|
|
|
NULL, NULL, NULL, NULL)
|
|
|
|
|
|
|
|
#define INIT_OBJ_RES_DATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, \
|
|
|
|
_data_ptr, _data_len) \
|
|
|
|
INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, true, \
|
|
|
|
_data_ptr, _data_len, NULL, NULL, NULL, NULL)
|
|
|
|
|
|
|
|
#define INIT_OBJ_RES_OPTDATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx) \
|
|
|
|
INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, true, \
|
|
|
|
NULL, NULL, NULL, NULL)
|
|
|
|
|
|
|
|
#define INIT_OBJ_RES_EXECUTE(_id, _r_ptr, _r_idx, _ex_cb) \
|
|
|
|
do { \
|
|
|
|
_INIT_OBJ_RES(_id, _r_ptr, _r_idx, NULL, 0, \
|
|
|
|
NULL, NULL, NULL, _ex_cb); \
|
|
|
|
++_r_idx; \
|
|
|
|
} while (false)
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-11-24 18:47:00 +08:00
|
|
|
|
|
|
|
#define LWM2M_ATTR_PMIN 0
|
|
|
|
#define LWM2M_ATTR_PMAX 1
|
|
|
|
#define LWM2M_ATTR_GT 2
|
|
|
|
#define LWM2M_ATTR_LT 3
|
|
|
|
#define LWM2M_ATTR_STEP 4
|
|
|
|
#define NR_LWM2M_ATTR 5
|
|
|
|
|
|
|
|
/* TODO: support multiple server (sec 5.4.2) */
|
|
|
|
struct lwm2m_attr {
|
2018-05-07 15:05:04 -07:00
|
|
|
void *ref;
|
|
|
|
|
|
|
|
/* values */
|
2017-11-24 18:47:00 +08:00
|
|
|
union {
|
|
|
|
float32_value_t float_val;
|
2020-05-27 11:26:57 -05:00
|
|
|
int32_t int_val;
|
2017-11-24 18:47:00 +08:00
|
|
|
};
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t type;
|
2017-11-24 18:47:00 +08:00
|
|
|
};
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
struct lwm2m_engine_res_inst {
|
2018-05-07 13:33:48 -07:00
|
|
|
void *data_ptr;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t data_len;
|
|
|
|
uint16_t res_inst_id; /* 65535 == not "created" */
|
|
|
|
uint8_t data_flags;
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
2019-07-29 10:09:00 -07:00
|
|
|
struct lwm2m_engine_res {
|
|
|
|
lwm2m_engine_get_data_cb_t read_cb;
|
|
|
|
lwm2m_engine_get_data_cb_t pre_write_cb;
|
|
|
|
lwm2m_engine_set_data_cb_t post_write_cb;
|
|
|
|
lwm2m_engine_user_cb_t execute_cb;
|
|
|
|
|
|
|
|
struct lwm2m_engine_res_inst *res_instances;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t res_id;
|
|
|
|
uint8_t res_inst_count;
|
2019-07-29 10:09:00 -07:00
|
|
|
};
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
struct lwm2m_engine_obj_inst {
|
2018-05-07 13:33:48 -07:00
|
|
|
/* instance list */
|
2017-07-07 11:04:03 -07:00
|
|
|
sys_snode_t node;
|
2018-05-07 13:33:48 -07:00
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
struct lwm2m_engine_obj *obj;
|
2019-07-29 10:09:00 -07:00
|
|
|
struct lwm2m_engine_res *resources;
|
2017-11-24 18:47:00 +08:00
|
|
|
|
2018-05-07 13:33:48 -07:00
|
|
|
/* object instance member data */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t obj_inst_id;
|
|
|
|
uint16_t resource_count;
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
2019-07-29 10:09:00 -07:00
|
|
|
/* Initialize resource instances prior to use */
|
|
|
|
static inline void init_res_instance(struct lwm2m_engine_res_inst *ri,
|
|
|
|
size_t ri_len)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
memset(ri, 0, sizeof(*ri) * ri_len);
|
|
|
|
for (i = 0; i < ri_len; i++) {
|
|
|
|
ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
struct lwm2m_output_context {
|
|
|
|
const struct lwm2m_writer *writer;
|
2017-10-19 16:27:32 -07:00
|
|
|
struct coap_packet *out_cpkt;
|
|
|
|
|
2018-08-29 13:51:17 -07:00
|
|
|
/* private output data */
|
|
|
|
void *user_data;
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct lwm2m_input_context {
|
|
|
|
const struct lwm2m_reader *reader;
|
2017-10-19 16:27:32 -07:00
|
|
|
struct coap_packet *in_cpkt;
|
|
|
|
|
2019-01-25 14:13:07 -08:00
|
|
|
/* current position in buffer */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t offset;
|
2017-10-19 16:27:32 -07:00
|
|
|
|
2017-10-26 23:32:47 -07:00
|
|
|
/* length of incoming opaque */
|
net: lwm2m: Fix opaque data transfer in block mode
When FW update in PUSH mode is used, the firmware is encapsulated in the
TLV as an opaque data, according to the LMWM2M satandard, and then
sliced into blocks and transferred block by block in several
transactions. Therefore, the TLV header is only present in the initial
message.
Current implementation did not handle this case well, reporting errors
on consecutive blocks, therefore making the FW update in PUSH mode
broken.
This commit fixes this issue with following changes:
* The TLV is only assumed to be present in the initial block, while
consecutive blocks will be processed directly into the appropriate
handler,
* 32-bit variables shall be used whenever dealing with the opaque data
length, since the firmware size can easily exceed the 16-bit range,
* Additional information, required for the FW block transfer to work
properly were added to the block context structure,
* The application shall only be notified of the actual data length, and
not the total block size (the total TLV size including header).
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
2020-06-03 10:48:44 +02:00
|
|
|
size_t opaque_len;
|
2019-01-25 15:45:14 -08:00
|
|
|
|
|
|
|
/* private output data */
|
|
|
|
void *user_data;
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
2019-01-24 14:40:23 -08:00
|
|
|
/* Establish a message timeout callback */
|
|
|
|
typedef void (*lwm2m_message_timeout_cb_t)(struct lwm2m_message *msg);
|
|
|
|
|
|
|
|
/* Internal LwM2M message structure to track in-flight messages. */
|
|
|
|
struct lwm2m_message {
|
|
|
|
/** LwM2M context related to this message */
|
|
|
|
struct lwm2m_ctx *ctx;
|
|
|
|
|
|
|
|
/** Incoming / outgoing contexts */
|
|
|
|
struct lwm2m_input_context in;
|
|
|
|
struct lwm2m_output_context out;
|
|
|
|
|
|
|
|
/** Incoming path */
|
|
|
|
struct lwm2m_obj_path path;
|
|
|
|
|
|
|
|
/** CoAP packet data related to the outgoing message */
|
|
|
|
struct coap_packet cpkt;
|
|
|
|
|
2019-01-25 14:13:07 -08:00
|
|
|
/** Buffer data related outgoing message */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t msg_data[MAX_PACKET_SIZE];
|
2019-01-25 14:13:07 -08:00
|
|
|
|
2019-01-24 14:40:23 -08:00
|
|
|
/** Message transmission handling for TYPE_CON */
|
|
|
|
struct coap_pending *pending;
|
|
|
|
struct coap_reply *reply;
|
|
|
|
|
|
|
|
/** Message configuration */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t *token;
|
2019-01-24 14:40:23 -08:00
|
|
|
coap_reply_t reply_cb;
|
|
|
|
lwm2m_message_timeout_cb_t message_timeout_cb;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t mid;
|
|
|
|
uint8_t type;
|
|
|
|
uint8_t code;
|
|
|
|
uint8_t tkl;
|
2019-01-24 14:40:23 -08:00
|
|
|
|
|
|
|
/** Incoming message action */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t operation;
|
2019-01-24 14:40:23 -08:00
|
|
|
|
|
|
|
/** Counter for message re-send / abort handling */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t send_attempts;
|
2019-01-24 14:40:23 -08:00
|
|
|
};
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* LWM2M format writer for the various formats supported */
|
|
|
|
struct lwm2m_writer {
|
|
|
|
size_t (*put_begin)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
|
|
|
size_t (*put_end)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
2018-08-29 14:26:24 -07:00
|
|
|
size_t (*put_begin_oi)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
|
|
|
size_t (*put_end_oi)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
|
|
|
size_t (*put_begin_r)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
|
|
|
size_t (*put_end_r)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*put_begin_ri)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
|
|
|
size_t (*put_end_ri)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path);
|
|
|
|
size_t (*put_s8)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int8_t value);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*put_s16)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int16_t value);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*put_s32)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int32_t value);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*put_s64)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int64_t value);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*put_string)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2017-10-11 12:48:06 -07:00
|
|
|
char *buf, size_t buflen);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*put_float32fix)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
float32_value_t *value);
|
|
|
|
size_t (*put_float64fix)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
float64_value_t *value);
|
|
|
|
size_t (*put_bool)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
bool value);
|
2017-10-26 23:32:47 -07:00
|
|
|
size_t (*put_opaque)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
char *buf, size_t buflen);
|
2020-05-19 12:37:02 +02:00
|
|
|
size_t (*put_objlnk)(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
struct lwm2m_objlnk *value);
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct lwm2m_reader {
|
|
|
|
size_t (*get_s32)(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
int32_t *value);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*get_s64)(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
int64_t *value);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*get_string)(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t *buf, size_t buflen);
|
2017-07-07 11:04:03 -07:00
|
|
|
size_t (*get_float32fix)(struct lwm2m_input_context *in,
|
|
|
|
float32_value_t *value);
|
|
|
|
size_t (*get_float64fix)(struct lwm2m_input_context *in,
|
|
|
|
float64_value_t *value);
|
|
|
|
size_t (*get_bool)(struct lwm2m_input_context *in,
|
|
|
|
bool *value);
|
2017-10-26 23:32:47 -07:00
|
|
|
size_t (*get_opaque)(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t *buf, size_t buflen, bool *last_block);
|
2020-05-19 12:37:02 +02:00
|
|
|
size_t (*get_objlnk)(struct lwm2m_input_context *in,
|
|
|
|
struct lwm2m_objlnk *value);
|
2017-07-07 11:04:03 -07:00
|
|
|
};
|
|
|
|
|
2018-08-29 13:51:17 -07:00
|
|
|
/* output user_data management functions */
|
|
|
|
|
|
|
|
static inline void engine_set_out_user_data(struct lwm2m_output_context *out,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
out->user_data = user_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *engine_get_out_user_data(struct lwm2m_output_context *out)
|
|
|
|
{
|
|
|
|
return out->user_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
engine_clear_out_user_data(struct lwm2m_output_context *out)
|
|
|
|
{
|
|
|
|
out->user_data = NULL;
|
|
|
|
}
|
|
|
|
|
2019-01-25 15:45:14 -08:00
|
|
|
static inline void engine_set_in_user_data(struct lwm2m_input_context *in,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
in->user_data = user_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *engine_get_in_user_data(struct lwm2m_input_context *in)
|
|
|
|
{
|
|
|
|
return in->user_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
engine_clear_in_user_data(struct lwm2m_input_context *in)
|
|
|
|
{
|
|
|
|
in->user_data = NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* inline multi-format write / read functions */
|
|
|
|
|
|
|
|
static inline size_t engine_put_begin(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_begin) {
|
|
|
|
return out->writer->put_begin(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_end(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_end) {
|
|
|
|
return out->writer->put_end(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-29 14:26:24 -07:00
|
|
|
static inline size_t engine_put_begin_oi(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_begin_oi) {
|
|
|
|
return out->writer->put_begin_oi(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_end_oi(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_end_oi) {
|
|
|
|
return out->writer->put_end_oi(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_begin_r(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_begin_r) {
|
|
|
|
return out->writer->put_begin_r(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_end_r(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_end_r) {
|
|
|
|
return out->writer->put_end_r(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
static inline size_t engine_put_begin_ri(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_begin_ri) {
|
|
|
|
return out->writer->put_begin_ri(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_end_ri(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path)
|
|
|
|
{
|
|
|
|
if (out->writer->put_end_ri) {
|
|
|
|
return out->writer->put_end_ri(out, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_s8(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int8_t value)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
return out->writer->put_s8(out, path, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_s16(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int16_t value)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
return out->writer->put_s16(out, path, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_s32(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int32_t value)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
return out->writer->put_s32(out, path, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_s64(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2020-05-27 11:26:57 -05:00
|
|
|
int64_t value)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
return out->writer->put_s64(out, path, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_string(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
2017-10-11 12:48:06 -07:00
|
|
|
char *buf, size_t buflen)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2017-10-11 12:48:06 -07:00
|
|
|
return out->writer->put_string(out, path, buf, buflen);
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_float32fix(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
float32_value_t *value)
|
|
|
|
{
|
|
|
|
return out->writer->put_float32fix(out, path, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_float64fix(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
float64_value_t *value)
|
|
|
|
{
|
|
|
|
return out->writer->put_float64fix(out, path, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_put_bool(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
bool value)
|
|
|
|
{
|
|
|
|
return out->writer->put_bool(out, path, value);
|
|
|
|
}
|
|
|
|
|
2017-10-26 23:32:47 -07:00
|
|
|
static inline size_t engine_put_opaque(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
if (out->writer->put_opaque) {
|
|
|
|
return out->writer->put_opaque(out, path, buf, buflen);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-05-19 12:37:02 +02:00
|
|
|
static inline size_t engine_put_objlnk(struct lwm2m_output_context *out,
|
|
|
|
struct lwm2m_obj_path *path,
|
|
|
|
struct lwm2m_objlnk *value)
|
|
|
|
{
|
|
|
|
return out->writer->put_objlnk(out, path, value);
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
static inline size_t engine_get_s32(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
int32_t *value)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
return in->reader->get_s32(in, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_get_s64(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
int64_t *value)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
return in->reader->get_s64(in, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_get_string(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t *buf, size_t buflen)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2017-10-11 12:48:06 -07:00
|
|
|
return in->reader->get_string(in, buf, buflen);
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_get_float32fix(struct lwm2m_input_context *in,
|
|
|
|
float32_value_t *value)
|
|
|
|
{
|
|
|
|
return in->reader->get_float32fix(in, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_get_float64fix(struct lwm2m_input_context *in,
|
|
|
|
float64_value_t *value)
|
|
|
|
{
|
|
|
|
return in->reader->get_float64fix(in, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t engine_get_bool(struct lwm2m_input_context *in,
|
|
|
|
bool *value)
|
|
|
|
{
|
|
|
|
return in->reader->get_bool(in, value);
|
|
|
|
}
|
|
|
|
|
2017-10-26 23:32:47 -07:00
|
|
|
static inline size_t engine_get_opaque(struct lwm2m_input_context *in,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t *buf, size_t buflen,
|
2017-10-26 23:32:47 -07:00
|
|
|
bool *last_block)
|
|
|
|
{
|
|
|
|
if (in->reader->get_opaque) {
|
|
|
|
return in->reader->get_opaque(in, buf, buflen, last_block);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-05-19 12:37:02 +02:00
|
|
|
static inline size_t engine_get_objlnk(struct lwm2m_input_context *in,
|
|
|
|
struct lwm2m_objlnk *value)
|
|
|
|
{
|
|
|
|
return in->reader->get_objlnk(in, value);
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
#endif /* LWM2M_OBJECT_H_ */
|