1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define LOG_MODULE_NAME net_lwm2m_obj_portfolio
8 #define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
9 
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
12 
13 #include <stdint.h>
14 #include <zephyr/init.h>
15 
16 #include "lwm2m_object.h"
17 #include "lwm2m_engine.h"
18 #include "lwm2m_resource_ids.h"
19 
20 #define PORTFOLIO_VERSION_MAJOR 1
21 #define PORTFOLIO_VERSION_MINOR 0
22 
23 #define PORTFOLIO_IDENTITY_ID			0
24 #define PORTFOLIO_GET_AUTH_DATA_ID		1
25 #define PORTFOLIO_AUTH_DATA_ID			2
26 #define PORTFOLIO_AUTH_STATUS_ID		3
27 
28 #define PORTFOLIO_MAX_ID 4
29 
30 /* Identity max based on LwM2M v1.1 conformance test requirements */
31 #define PORTFOLIO_IDENTITY_MAX 4
32 #define PORTFOLIO_AUTH_DATA_MAX 4
33 /* Support 2 multi instance object */
34 #define MAX_INSTANCE_COUNT	2
35 
36 /* Default Identity buffer length 40 */
37 #define DEFAULT_IDENTITY_BUFFER_LENGTH 40
38 
39 /*
40  * Calculate resource instances as follows:
41  * start with PORTFOLIO_MAX_ID
42  * subtract MULTI resources and execute because their counts include 0 resource (3)
43  * add PORTFOLIO_IDENTITY_ID resource instances
44  * add PORTFOLIO_AUTH_DATA_ID resource instances
45  */
46 #define RESOURCE_INSTANCE_COUNT        (PORTFOLIO_MAX_ID - 3 + \
47 					PORTFOLIO_IDENTITY_MAX + \
48 					PORTFOLIO_AUTH_DATA_MAX)
49 
50 static struct lwm2m_engine_obj portfolio;
51 static struct lwm2m_engine_obj_field fields[] = {
52 	OBJ_FIELD_DATA(PORTFOLIO_IDENTITY_ID, RW, STRING), /* Mandatory, multi-instance */
53 	OBJ_FIELD_EXECUTE(PORTFOLIO_GET_AUTH_DATA_ID), /* Optional, single-instance */
54 	OBJ_FIELD_DATA(PORTFOLIO_AUTH_DATA_ID, R_OPT, OPAQUE), /* Optional, multi-instance */
55 	OBJ_FIELD_DATA(PORTFOLIO_AUTH_STATUS_ID, R_OPT, U8) /* Optional, single-instance*/
56 };
57 
58 
59 static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
60 static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][PORTFOLIO_MAX_ID];
61 static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
62 static char identity[MAX_INSTANCE_COUNT*PORTFOLIO_IDENTITY_MAX][DEFAULT_IDENTITY_BUFFER_LENGTH];
63 
portfolio_create(uint16_t obj_inst_id)64 static struct lwm2m_engine_obj_inst *portfolio_create(uint16_t obj_inst_id)
65 {
66 	int index, avail = -1, i = 0, j = 0, indentity_buffer_start = 0;
67 
68 	/* Check that there is no other instance with this ID */
69 	for (index = 0; index < ARRAY_SIZE(inst); index++) {
70 		if (index) {
71 			indentity_buffer_start += PORTFOLIO_IDENTITY_MAX;
72 		}
73 		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
74 			LOG_ERR("Can not create instance - "
75 				"already existing: %u",
76 				obj_inst_id);
77 			return NULL;
78 		}
79 
80 		/* Save first available slot index */
81 		if (avail < 0 && !inst[index].obj) {
82 			avail = index;
83 		}
84 	}
85 
86 	if (avail < 0) {
87 		LOG_ERR("Can not create instance - no more room: %u", obj_inst_id);
88 		return NULL;
89 	}
90 
91 	(void)memset(res[avail], 0, sizeof(res[avail][0]) * ARRAY_SIZE(res[avail]));
92 	(void)memset(identity[avail], 0, DEFAULT_IDENTITY_BUFFER_LENGTH);
93 
94 	init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail]));
95 
96 	/* initialize instance resource data */
97 	INIT_OBJ_RES_MULTI_DATA_LEN(PORTFOLIO_IDENTITY_ID, res[avail], i, res_inst[avail], j,
98 				    PORTFOLIO_IDENTITY_MAX, false, identity[indentity_buffer_start],
99 				    DEFAULT_IDENTITY_BUFFER_LENGTH, 0);
100 	INIT_OBJ_RES_EXECUTE(PORTFOLIO_GET_AUTH_DATA_ID, res[avail], i, NULL);
101 	INIT_OBJ_RES_MULTI_OPTDATA(PORTFOLIO_AUTH_DATA_ID, res[avail], i, res_inst[avail], j,
102 				   PORTFOLIO_AUTH_DATA_MAX, false);
103 	INIT_OBJ_RES_OPTDATA(PORTFOLIO_AUTH_STATUS_ID, res[avail], i, res_inst[avail], j);
104 
105 	inst[avail].resources = res[avail];
106 	inst[avail].resource_count = i;
107 
108 	LOG_DBG("Create LwM2M Portfolio instance: %d", obj_inst_id);
109 
110 	return &inst[avail];
111 }
112 
lwm2m_portfolio_init(void)113 static int lwm2m_portfolio_init(void)
114 {
115 	portfolio.obj_id = LWM2M_OBJECT_PORTFOLIO_ID;
116 	portfolio.version_major = PORTFOLIO_VERSION_MAJOR;
117 	portfolio.version_minor = PORTFOLIO_VERSION_MINOR;
118 	portfolio.is_core = false;
119 	portfolio.fields = fields;
120 	portfolio.field_count = ARRAY_SIZE(fields);
121 	portfolio.max_instance_count = MAX_INSTANCE_COUNT;
122 	portfolio.create_cb = portfolio_create;
123 	lwm2m_register_obj(&portfolio);
124 
125 	return 0;
126 }
127 
128 SYS_INIT(lwm2m_portfolio_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
129