From 3e861c04e9b619b15e1759d81a13831d3cb0a8d7 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 2 Feb 2022 15:39:59 +0100 Subject: [PATCH] net: lwm2m: Add LwM2M 1.1 discovery support LwM2M adds Resource Instance reporting in Discovery response, along with attributes assinged at the Resource Instance level. Signed-off-by: Robert Lubos --- subsys/net/lib/lwm2m/lwm2m_engine.c | 76 ++++++++++++++++++--- subsys/net/lib/lwm2m/lwm2m_engine.h | 2 + subsys/net/lib/lwm2m/lwm2m_rw_link_format.c | 62 +++++++++++++++++ 3 files changed, 132 insertions(+), 8 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index b2cb11fd59a..39f34beed70 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -3399,6 +3399,54 @@ move_forward: return ret; } +static int lwm2m_discover_add_res(struct lwm2m_message *msg, + struct lwm2m_engine_obj_inst *obj_inst, + struct lwm2m_engine_res *res) +{ + int ret; + struct lwm2m_obj_path path = { + .obj_id = obj_inst->obj->obj_id, + .obj_inst_id = obj_inst->obj_inst_id, + .res_id = res->res_id, + .level = LWM2M_PATH_LEVEL_RESOURCE, + }; + + ret = engine_put_corelink(&msg->out, &path); + if (ret < 0) { + return ret; + } + + /* Report resource instances, if applicable. */ + if (IS_ENABLED(CONFIG_LWM2M_VERSION_1_1) && + msg->path.level == LWM2M_PATH_LEVEL_RESOURCE && + res->multi_res_inst) { + for (int i = 0; i < res->res_inst_count; i++) { + struct lwm2m_engine_res_inst *res_inst = + &res->res_instances[i]; + + if (res_inst->res_inst_id == + RES_INSTANCE_NOT_CREATED) { + continue; + } + + path = (struct lwm2m_obj_path){ + .obj_id = obj_inst->obj->obj_id, + .obj_inst_id = obj_inst->obj_inst_id, + .res_id = res->res_id, + .res_inst_id = res_inst->res_inst_id, + .level = LWM2M_PATH_LEVEL_RESOURCE_INST, + }; + + ret = engine_put_corelink(&msg->out, &path); + if (ret < 0) { + return ret; + } + } + } + + return 0; +} + int lwm2m_discover_handler(struct lwm2m_message *msg, bool is_bootstrap) { struct lwm2m_engine_obj *obj; @@ -3515,14 +3563,8 @@ int lwm2m_discover_handler(struct lwm2m_message *msg, bool is_bootstrap) continue; } - struct lwm2m_obj_path path = { - .obj_id = obj_inst->obj->obj_id, - .obj_inst_id = obj_inst->obj_inst_id, - .res_id = obj_inst->resources[i].res_id, - .level = LWM2M_PATH_LEVEL_RESOURCE, - }; - - ret = engine_put_corelink(&msg->out, &path); + ret = lwm2m_discover_add_res(msg, obj_inst, + &obj_inst->resources[i]); if (ret < 0) { return ret; } @@ -3646,6 +3688,24 @@ struct lwm2m_engine_res *lwm2m_engine_get_res( return res; } +struct lwm2m_engine_res_inst *lwm2m_engine_get_res_inst( + const struct lwm2m_obj_path *path) +{ + struct lwm2m_engine_res_inst *res_inst = NULL; + int ret; + + if (path->level != LWM2M_PATH_LEVEL_RESOURCE_INST) { + return NULL; + } + + ret = path_to_objs(path, NULL, NULL, NULL, &res_inst); + if (ret < 0) { + return NULL; + } + + return res_inst; +} + bool lwm2m_engine_shall_report_obj_version(const struct lwm2m_engine_obj *obj) { if (obj->is_core) { diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.h b/subsys/net/lib/lwm2m/lwm2m_engine.h index 235af591a2c..a4c19071429 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.h +++ b/subsys/net/lib/lwm2m/lwm2m_engine.h @@ -87,6 +87,8 @@ struct lwm2m_engine_obj_inst *lwm2m_engine_get_obj_inst( const struct lwm2m_obj_path *path); struct lwm2m_engine_res *lwm2m_engine_get_res( const struct lwm2m_obj_path *path); +struct lwm2m_engine_res_inst *lwm2m_engine_get_res_inst( + const struct lwm2m_obj_path *path); bool lwm2m_engine_shall_report_obj_version(const struct lwm2m_engine_obj *obj); diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c b/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c index acfe1cb213d..d8fc6c93d89 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_link_format.c @@ -436,6 +436,55 @@ static int put_res_corelink(struct lwm2m_output_context *out, return len; } +static int put_res_inst_corelink(struct lwm2m_output_context *out, + const struct lwm2m_obj_path *path, + struct link_format_out_formatter_data *fd) +{ + char obj_buf[CORELINK_BUF_SIZE]; + int len = 0; + int ret; + + if (fd->mode != LINK_FORMAT_MODE_DISCOVERY) { + /* Report resources instances only in device management + * discovery. + */ + return 0; + } + + ret = snprintk(obj_buf, sizeof(obj_buf), "", path->obj_id, + path->obj_inst_id, path->res_id, path->res_inst_id); + if (ret < 0 || ret >= sizeof(obj_buf)) { + return -ENOMEM; + } + + len += ret; + + ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), obj_buf, len); + if (ret < 0) { + return ret; + } + + /* Report resource instance attrs only when resource was specified. */ + if (fd->request_level == LWM2M_PATH_LEVEL_RESOURCE) { + struct lwm2m_engine_res_inst *res_inst = + lwm2m_engine_get_res_inst(path); + + if (res_inst == NULL) { + return -EINVAL; + } + + ret = put_corelink_attributes(out, res_inst, obj_buf, + sizeof(obj_buf)); + if (ret < 0) { + return ret; + } + + len += ret; + } + + return len; +} + static int put_corelink(struct lwm2m_output_context *out, const struct lwm2m_obj_path *path) { @@ -487,6 +536,19 @@ static int put_corelink(struct lwm2m_output_context *out, len += ret; break; + case LWM2M_PATH_LEVEL_RESOURCE_INST: + if (IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) { + ret = put_res_inst_corelink(out, path, fd); + if (ret < 0) { + return ret; + } + + len += ret; + break; + } + + __fallthrough; + default: LOG_ERR("Invalid corelink path level: %d", path->level); return -EINVAL;