net: lwm2m: introduce FLAG_OPTIONAL to denote optional resources

This patch introduces several changes to support OPTIONAL resources.

The primary indicator for this behavior is to assign FLAG_OPTIONAL
to the object field's permission flags.

These resources are not setup by the LwM2M object code.  They are
left up to the user-based code for initialization via the following
functions:
lwm2m_engine_set_res_data()
lwm2m_engine_get_res_data()

When assigning const-based data as a data buffer, user-based code can
also specify the following data flag: LWM2M_RES_DATA_FLAG_RO

The FLAG_OPTIONAL flag also affects the LwM2M engine in the following
ways:
- CREATE operations won't generate an error if optional resources are
  not included.
- Object instance READ operations won't complain about missing
  optional resources.
- In the future, BOOTSTRAP operations can have different handling
  based on optional resources.

Signed-off-by: Michael Scott <michael@opensourcefoundries.com>
This commit is contained in:
Michael Scott 2018-04-30 16:43:25 -07:00 committed by Jukka Rissanen
commit 0d67f6a78d
3 changed files with 113 additions and 2 deletions

View file

@ -1344,6 +1344,38 @@ int lwm2m_engine_create_obj_inst(char *pathstr)
return lwm2m_create_obj_inst(path.obj_id, path.obj_inst_id, &obj_inst);
}
int lwm2m_engine_set_res_data(char *pathstr, void *data_ptr, u16_t data_len,
u8_t data_flags)
{
struct lwm2m_obj_path path;
struct lwm2m_engine_res_inst *res = NULL;
int ret = 0;
/* translate path -> path_obj */
ret = string_to_path(pathstr, &path, '/');
if (ret < 0) {
return ret;
}
if (path.level < 3) {
SYS_LOG_ERR("path must have 3 parts");
return -EINVAL;
}
/* look up resource obj */
ret = path_to_objs(&path, NULL, NULL, &res);
if (ret < 0) {
return ret;
}
/* assign data elements */
res->data_ptr = data_ptr;
res->data_len = data_len;
res->data_flags = data_flags;
return ret;
}
static int lwm2m_engine_set(char *pathstr, void *value, u16_t len)
{
struct lwm2m_obj_path path;
@ -1379,6 +1411,11 @@ static int lwm2m_engine_set(char *pathstr, void *value, u16_t len)
return -ENOENT;
}
if (LWM2M_HAS_RES_FLAG(res, LWM2M_RES_DATA_FLAG_RO)) {
SYS_LOG_ERR("res data pointer is read-only");
return -EACCES;
}
/* setup initial data elements */
data_ptr = res->data_ptr;
data_len = res->data_len;
@ -1555,6 +1592,37 @@ int lwm2m_engine_set_float64(char *pathstr, float64_value_t *value)
/* user data getter functions */
int lwm2m_engine_get_res_data(char *pathstr, void **data_ptr, u16_t *data_len,
u8_t *data_flags)
{
struct lwm2m_obj_path path;
struct lwm2m_engine_res_inst *res = NULL;
int ret = 0;
/* translate path -> path_obj */
ret = string_to_path(pathstr, &path, '/');
if (ret < 0) {
return ret;
}
if (path.level < 3) {
SYS_LOG_ERR("path must have 3 parts");
return -EINVAL;
}
/* look up resource obj */
ret = path_to_objs(&path, NULL, NULL, &res);
if (ret < 0) {
return ret;
}
*data_ptr = res->data_ptr;
*data_len = res->data_len;
*data_flags = res->data_flags;
return 0;
}
static int lwm2m_engine_get(char *pathstr, void *buf, u16_t buflen)
{
int ret = 0;
@ -2052,6 +2120,10 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst,
in = context->in;
path = context->path;
if (LWM2M_HAS_RES_FLAG(res, LWM2M_RES_DATA_FLAG_RO)) {
return -EACCES;
}
/* setup initial data elements */
data_ptr = res->data_ptr;
data_len = res->data_len;
@ -2655,8 +2727,12 @@ static int do_read_op(struct lwm2m_engine_obj *obj,
ret = lwm2m_read_handler(obj_inst, res,
obj_field, context);
if (ret < 0) {
/* What to do here? */
SYS_LOG_ERR("READ OP failed: %d", ret);
/* ignore errors unless MATCH_SINGLE */
if (match_type == MATCH_SINGLE &&
!LWM2M_HAS_PERM(obj_field,
BIT(LWM2M_FLAG_OPTIONAL))) {
SYS_LOG_ERR("READ OP: %d", ret);
}
} else {
num_read += 1;
}