diff --git a/include/net/lwm2m.h b/include/net/lwm2m.h index 4b282ab0d5f..66a6e747578 100644 --- a/include/net/lwm2m.h +++ b/include/net/lwm2m.h @@ -124,6 +124,12 @@ struct lwm2m_ctx { * callback in case of socket errors on receive. */ lwm2m_socket_fault_cb_t fault_cb; + + /** Validation buffer. Used as a temporary buffer to decode the resource + * value before validation. On successful validation, its content is + * copied into the actual resource buffer. + */ + uint8_t validate_buf[CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE]; }; @@ -159,6 +165,7 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id, * objects. * * A function of this type can be registered via: + * lwm2m_engine_register_validate_callback() * lwm2m_engine_register_post_write_callback() * * @param[in] obj_inst_id Object instance ID generating the callback. @@ -746,6 +753,29 @@ int lwm2m_engine_register_read_callback(char *pathstr, int lwm2m_engine_register_pre_write_callback(char *pathstr, lwm2m_engine_get_data_cb_t cb); +/** + * @brief Set resource (instance) validation callback + * + * This callback is triggered before setting the value of a resource to the + * resource data buffer. + * + * The callback allows an LwM2M client or object to validate the data before + * writing and notify an error if the data should be discarded for any reason + * (by returning a negative error code). + * + * @note All resources that have a validation callback registered are initially + * decoded into a temporary validation buffer. Make sure that + * ``CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE`` is large enough to + * store each of the validated resources (individually). + * + * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)" + * @param[in] cb Validate resource data callback + * + * @return 0 for success or negative in case of error. + */ +int lwm2m_engine_register_validate_callback(char *pathstr, + lwm2m_engine_set_data_cb_t cb); + /** * @brief Set resource (instance) post-write callback * diff --git a/subsys/net/lib/lwm2m/Kconfig b/subsys/net/lib/lwm2m/Kconfig index 147cf011f77..47c4a9278d2 100644 --- a/subsys/net/lib/lwm2m/Kconfig +++ b/subsys/net/lib/lwm2m/Kconfig @@ -56,6 +56,16 @@ config LWM2M_ENGINE_MESSAGE_HEADER_SIZE help Extra room allocated to handle CoAP header data +config LWM2M_ENGINE_VALIDATION_BUFFER_SIZE + int "Size of the validation buffer for the incoming data" + default 64 + help + LwM2M will use the validation buffer during the write operation, to + decode the resource value before validating it (applies for resources + for which validation callback has been registered). Set this value to + the maximum expected size of the resources that need to be validated + (and thus have validation callback registered). + config LWM2M_ENGINE_MAX_PENDING int "LWM2M engine max. pending objects" default 5 diff --git a/subsys/net/lib/lwm2m/ipso_buzzer.c b/subsys/net/lib/lwm2m/ipso_buzzer.c index 21ab78f997e..8f9e74b1fdb 100644 --- a/subsys/net/lib/lwm2m/ipso_buzzer.c +++ b/subsys/net/lib/lwm2m/ipso_buzzer.c @@ -216,7 +216,7 @@ static struct lwm2m_engine_obj_inst *buzzer_create(uint16_t obj_inst_id) res_inst[avail], j, 1, false, true, &buzzer_data[avail].onoff, sizeof(buzzer_data[avail].onoff), - NULL, NULL, onoff_post_write_cb, NULL); + NULL, NULL, NULL, onoff_post_write_cb, NULL); INIT_OBJ_RES_DATA(BUZZER_LEVEL_ID, res[avail], i, res_inst[avail], j, &buzzer_data[avail].level, sizeof(buzzer_data[avail].level)); diff --git a/subsys/net/lib/lwm2m/ipso_generic_sensor.c b/subsys/net/lib/lwm2m/ipso_generic_sensor.c index 311f009c4ad..359d4bc40b9 100644 --- a/subsys/net/lib/lwm2m/ipso_generic_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_generic_sensor.c @@ -207,7 +207,7 @@ static struct lwm2m_engine_obj_inst *generic_sensor_create(uint16_t obj_inst_id) /* initialize instance resource data */ INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), - NULL, NULL, sensor_value_write_cb, NULL); + NULL, NULL, NULL, sensor_value_write_cb, NULL); INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, units[index], UNIT_STR_MAX_SIZE); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, diff --git a/subsys/net/lib/lwm2m/ipso_humidity_sensor.c b/subsys/net/lib/lwm2m/ipso_humidity_sensor.c index b39a2a31d31..1bec5c1d274 100644 --- a/subsys/net/lib/lwm2m/ipso_humidity_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_humidity_sensor.c @@ -190,7 +190,7 @@ humidity_sensor_create(uint16_t obj_inst_id) /* initialize instance resource data */ INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), - NULL, NULL, sensor_value_write_cb, NULL); + NULL, NULL, NULL, sensor_value_write_cb, NULL); INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, units[index], UNIT_STR_MAX_SIZE); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, diff --git a/subsys/net/lib/lwm2m/ipso_light_control.c b/subsys/net/lib/lwm2m/ipso_light_control.c index a75006177a8..79ce2bdf308 100644 --- a/subsys/net/lib/lwm2m/ipso_light_control.c +++ b/subsys/net/lib/lwm2m/ipso_light_control.c @@ -173,7 +173,7 @@ static struct lwm2m_engine_obj_inst *light_control_create(uint16_t obj_inst_id) INIT_OBJ_RES(LIGHT_ON_TIME_ID, res[avail], i, res_inst[avail], j, 1, false, true, &on_time_value[avail], sizeof(*on_time_value), - on_time_read_cb, NULL, on_time_post_write_cb, NULL); + on_time_read_cb, NULL, NULL, on_time_post_write_cb, NULL); INIT_OBJ_RES_DATA(LIGHT_CUMULATIVE_ACTIVE_POWER_ID, res[avail], i, res_inst[avail], j, &cumulative_active_value[avail], diff --git a/subsys/net/lib/lwm2m/ipso_onoff_switch.c b/subsys/net/lib/lwm2m/ipso_onoff_switch.c index 9d85e8055f1..4889f0fe8c9 100644 --- a/subsys/net/lib/lwm2m/ipso_onoff_switch.c +++ b/subsys/net/lib/lwm2m/ipso_onoff_switch.c @@ -214,17 +214,17 @@ static struct lwm2m_engine_obj_inst *switch_create(uint16_t obj_inst_id) res_inst[avail], j, 1, false, true, &switch_data[avail].state, sizeof(switch_data[avail].state), - NULL, NULL, state_post_write_cb, NULL); + NULL, NULL, NULL, state_post_write_cb, NULL); INIT_OBJ_RES_DATA(SWITCH_DIGITAL_INPUT_COUNTER_ID, res[avail], i, res_inst[avail], j, &switch_data[avail].counter, sizeof(switch_data[avail].counter)); INIT_OBJ_RES_OPT(SWITCH_ON_TIME_ID, res[avail], i, res_inst[avail], j, 1, false, true, - on_time_read_cb, NULL, time_post_write_cb, NULL); + on_time_read_cb, NULL, NULL, time_post_write_cb, NULL); INIT_OBJ_RES_OPT(SWITCH_OFF_TIME_ID, res[avail], i, res_inst[avail], j, 1, false, true, - off_time_read_cb, NULL, time_post_write_cb, NULL); + off_time_read_cb, NULL, NULL, time_post_write_cb, NULL); INIT_OBJ_RES_OPTDATA(SWITCH_APPLICATION_TYPE_ID, res[avail], i, res_inst[avail], j); #if ADD_TIMESTAMPS diff --git a/subsys/net/lib/lwm2m/ipso_pressure_sensor.c b/subsys/net/lib/lwm2m/ipso_pressure_sensor.c index ed1f7e2cc17..1c5ca10e990 100644 --- a/subsys/net/lib/lwm2m/ipso_pressure_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_pressure_sensor.c @@ -190,7 +190,7 @@ pressure_sensor_create(uint16_t obj_inst_id) /* initialize instance resource data */ INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), - NULL, NULL, sensor_value_write_cb, NULL); + NULL, NULL, NULL, sensor_value_write_cb, NULL); INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j, units[index], UNIT_STR_MAX_SIZE); INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i, diff --git a/subsys/net/lib/lwm2m/ipso_push_button.c b/subsys/net/lib/lwm2m/ipso_push_button.c index 9ad883fcfac..52a2dcd8942 100644 --- a/subsys/net/lib/lwm2m/ipso_push_button.c +++ b/subsys/net/lib/lwm2m/ipso_push_button.c @@ -146,7 +146,7 @@ static struct lwm2m_engine_obj_inst *button_create(uint16_t obj_inst_id) res_inst[avail], j, 1, false, true, &button_data[avail].state, sizeof(button_data[avail].state), - NULL, NULL, state_post_write_cb, NULL); + NULL, NULL, NULL, state_post_write_cb, NULL); INIT_OBJ_RES_DATA(BUTTON_DIGITAL_INPUT_COUNTER_ID, res[avail], i, res_inst[avail], j, &button_data[avail].counter, diff --git a/subsys/net/lib/lwm2m/ipso_temp_sensor.c b/subsys/net/lib/lwm2m/ipso_temp_sensor.c index 11e50805642..3d5ee5be843 100644 --- a/subsys/net/lib/lwm2m/ipso_temp_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_temp_sensor.c @@ -205,7 +205,7 @@ static struct lwm2m_engine_obj_inst *temp_sensor_create(uint16_t obj_inst_id) INIT_OBJ_RES(TEMP_SENSOR_VALUE_ID, res[index], i, res_inst[index], j, 1, false, true, &sensor_value[index], sizeof(*sensor_value), - NULL, NULL, sensor_value_write_cb, NULL); + NULL, NULL, NULL, sensor_value_write_cb, NULL); INIT_OBJ_RES_DATA(TEMP_UNITS_ID, res[index], i, res_inst[index], j, units[index], TEMP_STRING_SHORT); INIT_OBJ_RES_DATA(TEMP_MIN_MEASURED_VALUE_ID, res[index], i, diff --git a/subsys/net/lib/lwm2m/ipso_timer.c b/subsys/net/lib/lwm2m/ipso_timer.c index c3cb0c45d3c..407369c9b2b 100644 --- a/subsys/net/lib/lwm2m/ipso_timer.c +++ b/subsys/net/lib/lwm2m/ipso_timer.c @@ -344,7 +344,7 @@ static struct lwm2m_engine_obj_inst *timer_create(uint16_t obj_inst_id) res_inst[avail], j, 1, false, true, &timer_data[avail].remaining_time, sizeof(timer_data[avail].remaining_time), - remaining_time_read_cb, NULL, NULL, NULL); + remaining_time_read_cb, NULL, NULL, NULL, NULL); INIT_OBJ_RES_DATA(TIMER_MINIMUM_OFF_TIME_ID, res[avail], i, res_inst[avail], j, &timer_data[avail].min_off_time, sizeof(timer_data[avail].min_off_time)); @@ -354,12 +354,12 @@ static struct lwm2m_engine_obj_inst *timer_create(uint16_t obj_inst_id) res_inst[avail], j, 1, false, true, &timer_data[avail].enabled, sizeof(timer_data[avail].enabled), - NULL, NULL, enabled_post_write_cb, NULL); + NULL, NULL, NULL, enabled_post_write_cb, NULL); INIT_OBJ_RES(TIMER_CUMULATIVE_TIME_ID, res[avail], i, res_inst[avail], j, 1, false, true, &timer_data[avail].cumulative_time, sizeof(timer_data[avail].cumulative_time), - cumulative_time_read_cb, NULL, + cumulative_time_read_cb, NULL, NULL, cumulative_time_post_write_cb, NULL); INIT_OBJ_RES_DATA(TIMER_DIGITAL_STATE_ID, res[avail], i, res_inst[avail], j, &timer_data[avail].active, @@ -368,7 +368,7 @@ static struct lwm2m_engine_obj_inst *timer_create(uint16_t obj_inst_id) res_inst[avail], j, 1, false, true, &timer_data[avail].trigger_counter, sizeof(timer_data[avail].trigger_counter), - NULL, NULL, trigger_counter_post_write_cb, NULL); + NULL, NULL, NULL, trigger_counter_post_write_cb, NULL); INIT_OBJ_RES_DATA(TIMER_MODE_ID, res[avail], i, res_inst[avail], j, &timer_data[avail].timer_mode, sizeof(timer_data[avail].timer_mode)); diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index 2727cee6613..9879793caaf 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -1500,6 +1500,15 @@ static int lwm2m_engine_set(char *pathstr, void *value, uint16_t len) changed = true; } + if (res->validate_cb) { + ret = res->validate_cb(obj_inst->obj_inst_id, res->res_id, + res_inst->res_inst_id, value, + len, false, 0); + if (ret < 0) { + return -EINVAL; + } + } + switch (obj_field->data_type) { case LWM2M_RES_TYPE_OPAQUE: @@ -2103,6 +2112,21 @@ int lwm2m_engine_register_pre_write_callback(char *pathstr, return 0; } +int lwm2m_engine_register_validate_callback(char *pathstr, + lwm2m_engine_set_data_cb_t cb) +{ + int ret; + struct lwm2m_engine_res *res = NULL; + + ret = lwm2m_engine_get_resource(pathstr, &res); + if (ret < 0) { + return ret; + } + + res->validate_cb = cb; + return 0; +} + int lwm2m_engine_register_post_write_callback(char *pathstr, lwm2m_engine_set_data_cb_t cb) { @@ -2350,7 +2374,7 @@ size_t lwm2m_engine_get_opaque_more(struct lwm2m_input_context *in, static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_engine_res *res, struct lwm2m_engine_res_inst *res_inst, - struct lwm2m_input_context *in, + struct lwm2m_message *msg, void *data_ptr, size_t data_len) { size_t len = 1; @@ -2358,22 +2382,51 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, int ret = 0; bool last_block = true; struct lwm2m_opaque_context opaque_ctx = { 0 }; + void *write_buf; + size_t write_buf_len; - if (in->block_ctx != NULL) { - last_block = in->block_ctx->last_block; + if (msg->in.block_ctx != NULL) { + last_block = msg->in.block_ctx->last_block; /* Restore the opaque context from the block context, if used. */ - opaque_ctx = in->block_ctx->opaque; + opaque_ctx = msg->in.block_ctx->opaque; + } + + /* In case validation callback is present, write data to the temporary + * buffer first, for validation. Otherwise, write to the data buffer + * directly. + */ + if (res->validate_cb) { + write_buf = msg->ctx->validate_buf; + write_buf_len = sizeof(msg->ctx->validate_buf); + } else { + write_buf = data_ptr; + write_buf_len = data_len; } while (!last_pkt_block && len > 0) { - len = engine_get_opaque(in, (uint8_t *)data_ptr, - data_len, &opaque_ctx, &last_pkt_block); + len = engine_get_opaque(&msg->in, write_buf, + MIN(data_len, write_buf_len), + &opaque_ctx, &last_pkt_block); if (len == 0) { /* ignore empty content and continue */ return 0; } + + if (res->validate_cb) { + ret = res->validate_cb( + obj_inst->obj_inst_id, res->res_id, + res_inst->res_inst_id, write_buf, len, + last_pkt_block && last_block, opaque_ctx.len); + if (ret < 0) { + /* -EEXIST will generate Bad Request LWM2M response. */ + return -EEXIST; + } + + memcpy(data_ptr, write_buf, len); + } + if (res->post_write_cb) { ret = res->post_write_cb( obj_inst->obj_inst_id, res->res_id, @@ -2385,8 +2438,8 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, } } - if (in->block_ctx != NULL) { - in->block_ctx->opaque = opaque_ctx; + if (msg->in.block_ctx != NULL) { + msg->in.block_ctx->opaque = opaque_ctx; } return opaque_ctx.len; @@ -2407,6 +2460,8 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, int32_t temp32 = 0; int ret = 0; bool last_block = true; + void *write_buf; + size_t write_buf_len; if (!obj_inst || !res || !res_inst || !obj_field || !msg) { return -EINVAL; @@ -2427,7 +2482,7 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, &data_len); } - if (res->post_write_cb) { + if (res->post_write_cb || res->validate_cb) { if (msg->in.block_ctx != NULL) { /* Get block_ctx for total_size (might be zero) */ total_size = msg->in.block_ctx->ctx.total_size; @@ -2439,12 +2494,24 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, } } + /* In case validation callback is present, write data to the temporary + * buffer first, for validation. Otherwise, write to the data buffer + * directly. + */ + if (res->validate_cb) { + write_buf = msg->ctx->validate_buf; + write_buf_len = sizeof(msg->ctx->validate_buf); + } else { + write_buf = data_ptr; + write_buf_len = data_len; + } + if (data_ptr && data_len > 0) { switch (obj_field->data_type) { case LWM2M_RES_TYPE_OPAQUE: ret = lwm2m_write_handler_opaque(obj_inst, res, - res_inst, &msg->in, + res_inst, msg, data_ptr, data_len); if (ret < 0) { return ret; @@ -2454,77 +2521,77 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, break; case LWM2M_RES_TYPE_STRING: - engine_get_string(&msg->in, (uint8_t *)data_ptr, data_len); - len = strlen((char *)data_ptr); + engine_get_string(&msg->in, write_buf, write_buf_len); + len = strlen((char *)write_buf); break; case LWM2M_RES_TYPE_U64: engine_get_s64(&msg->in, &temp64); - *(uint64_t *)data_ptr = temp64; + *(uint64_t *)write_buf = temp64; len = 8; break; case LWM2M_RES_TYPE_U32: case LWM2M_RES_TYPE_TIME: engine_get_s32(&msg->in, &temp32); - *(uint32_t *)data_ptr = temp32; + *(uint32_t *)write_buf = temp32; len = 4; break; case LWM2M_RES_TYPE_U16: engine_get_s32(&msg->in, &temp32); - *(uint16_t *)data_ptr = temp32; + *(uint16_t *)write_buf = temp32; len = 2; break; case LWM2M_RES_TYPE_U8: engine_get_s32(&msg->in, &temp32); - *(uint8_t *)data_ptr = temp32; + *(uint8_t *)write_buf = temp32; len = 1; break; case LWM2M_RES_TYPE_S64: - engine_get_s64(&msg->in, (int64_t *)data_ptr); + engine_get_s64(&msg->in, (int64_t *)write_buf); len = 8; break; case LWM2M_RES_TYPE_S32: - engine_get_s32(&msg->in, (int32_t *)data_ptr); + engine_get_s32(&msg->in, (int32_t *)write_buf); len = 4; break; case LWM2M_RES_TYPE_S16: engine_get_s32(&msg->in, &temp32); - *(int16_t *)data_ptr = temp32; + *(int16_t *)write_buf = temp32; len = 2; break; case LWM2M_RES_TYPE_S8: engine_get_s32(&msg->in, &temp32); - *(int8_t *)data_ptr = temp32; + *(int8_t *)write_buf = temp32; len = 1; break; case LWM2M_RES_TYPE_BOOL: - engine_get_bool(&msg->in, (bool *)data_ptr); + engine_get_bool(&msg->in, (bool *)write_buf); len = 1; break; case LWM2M_RES_TYPE_FLOAT32: engine_get_float32fix(&msg->in, - (float32_value_t *)data_ptr); + (float32_value_t *)write_buf); len = sizeof(float32_value_t); break; case LWM2M_RES_TYPE_FLOAT64: engine_get_float64fix(&msg->in, - (float64_value_t *)data_ptr); + (float64_value_t *)write_buf); len = sizeof(float64_value_t); break; case LWM2M_RES_TYPE_OBJLNK: engine_get_objlnk(&msg->in, - (struct lwm2m_objlnk *)data_ptr); + (struct lwm2m_objlnk *)write_buf); len = sizeof(struct lwm2m_objlnk); break; @@ -2538,16 +2605,40 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, return -ENOENT; } - res_inst->data_len = len; + if (obj_field->data_type != LWM2M_RES_TYPE_OPAQUE) { + if (res->validate_cb) { + ret = res->validate_cb( + obj_inst->obj_inst_id, res->res_id, + res_inst->res_inst_id, write_buf, len, + last_block, total_size); + if (ret < 0) { + /* -EEXIST will generate Bad Request LWM2M response. */ + return -EEXIST; + } - if (res->post_write_cb && - obj_field->data_type != LWM2M_RES_TYPE_OPAQUE) { - ret = res->post_write_cb(obj_inst->obj_inst_id, - res->res_id, res_inst->res_inst_id, - data_ptr, len, - last_block, total_size); + if (len > data_len) { + LOG_ERR("Received data won't fit into provided " + "bufffer"); + return -ENOMEM; + } + + if (obj_field->data_type == LWM2M_RES_TYPE_STRING) { + strncpy(data_ptr, write_buf, data_len); + } else { + memcpy(data_ptr, write_buf, len); + } + } + + if (res->post_write_cb) { + ret = res->post_write_cb( + obj_inst->obj_inst_id, res->res_id, + res_inst->res_inst_id, data_ptr, len, + last_block, total_size); + } } + res_inst->data_len = len; + NOTIFY_OBSERVER_PATH(&msg->path); return ret; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_device.c b/subsys/net/lib/lwm2m/lwm2m_obj_device.c index c1aa3772eb6..f3b45aabf07 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_device.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_device.c @@ -229,7 +229,7 @@ static struct lwm2m_engine_obj_inst *device_create(uint16_t obj_inst_id) reset_error_list_cb); INIT_OBJ_RES_OPT(DEVICE_CURRENT_TIME_ID, res, i, res_inst, j, 1, false, true, current_time_read_cb, current_time_pre_write_cb, - current_time_post_write_cb, NULL); + NULL, current_time_post_write_cb, NULL); INIT_OBJ_RES_OPTDATA(DEVICE_UTC_OFFSET_ID, res, i, res_inst, j); INIT_OBJ_RES_OPTDATA(DEVICE_TIMEZONE_ID, res, i, res_inst, j); INIT_OBJ_RES_DATA(DEVICE_SUPPORTED_BINDING_MODES_ID, res, i, diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index 0e9cf19c09e..aec3f92e48f 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -320,10 +320,10 @@ static struct lwm2m_engine_obj_inst *firmware_create(uint16_t obj_inst_id) /* initialize instance resource data */ INIT_OBJ_RES_OPT(FIRMWARE_PACKAGE_ID, res, i, res_inst, j, 1, false, - true, NULL, NULL, package_write_cb, NULL); + true, NULL, NULL, NULL, package_write_cb, NULL); INIT_OBJ_RES(FIRMWARE_PACKAGE_URI_ID, res, i, res_inst, j, 1, false, true, package_uri, PACKAGE_URI_LEN, - NULL, NULL, package_uri_write_cb, NULL); + NULL, NULL, NULL, package_uri_write_cb, NULL); INIT_OBJ_RES_EXECUTE(FIRMWARE_UPDATE_ID, res, i, firmware_update_cb); INIT_OBJ_RES_DATA(FIRMWARE_STATE_ID, res, i, res_inst, j, &update_state, sizeof(update_state)); diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_server.c b/subsys/net/lib/lwm2m/lwm2m_obj_server.c index 89c0917f261..8dc891ab687 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_server.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_server.c @@ -213,7 +213,7 @@ static struct lwm2m_engine_obj_inst *server_create(uint16_t obj_inst_id) &server_id[index], sizeof(*server_id)); INIT_OBJ_RES(SERVER_LIFETIME_ID, res[index], i, res_inst[index], j, 1U, false, true, &lifetime[index], sizeof(*lifetime), - NULL, NULL, lifetime_write_cb, NULL); + NULL, NULL, NULL, lifetime_write_cb, NULL); INIT_OBJ_RES_DATA(SERVER_DEFAULT_MIN_PERIOD_ID, res[index], i, res_inst[index], j, &default_min_period[index], diff --git a/subsys/net/lib/lwm2m/lwm2m_object.h b/subsys/net/lib/lwm2m/lwm2m_object.h index 70aeb78156d..da51cfc23b8 100644 --- a/subsys/net/lib/lwm2m/lwm2m_object.h +++ b/subsys/net/lib/lwm2m/lwm2m_object.h @@ -198,13 +198,14 @@ struct lwm2m_engine_obj { /* Resource macros */ #define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, _multi_ri, \ - _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \ + _r_cb, _pre_w_cb, _val_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].multi_res_inst = _multi_ri; \ _r_ptr[_r_idx].read_cb = _r_cb; \ _r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \ + _r_ptr[_r_idx].validate_cb = _val_cb; \ _r_ptr[_r_idx].post_write_cb = _post_w_cb; \ _r_ptr[_r_idx].execute_cb = _ex_cb @@ -253,11 +254,11 @@ struct lwm2m_engine_obj { #define INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \ _data_ptr, _data_len, \ - _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \ + _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \ do { \ _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \ - _r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \ + _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \ _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \ _data_ptr, _data_len); \ ++_r_idx; \ @@ -266,11 +267,11 @@ struct lwm2m_engine_obj { #define INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \ _ri_ptr, _ri_idx, _ri_count, _multi_ri, _ri_create, \ - _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \ + _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb) \ do { \ _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ (_ri_ptr + _ri_idx), _ri_count, _multi_ri, \ - _r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \ + _r_cb, _pre_w_cb, _val_cb, _post_w_cb, _ex_cb); \ _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create); \ ++_r_idx; \ } while (false) @@ -280,27 +281,27 @@ struct lwm2m_engine_obj { _data_ptr, _data_len) \ INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ _ri_ptr, _ri_idx, _ri_count, true, _ri_create, \ - _data_ptr, _data_len, NULL, NULL, NULL, NULL) + _data_ptr, _data_len, NULL, 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, true, _ri_create, \ - NULL, NULL, NULL, NULL) + NULL, 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, false, true, \ - _data_ptr, _data_len, NULL, NULL, NULL, NULL) + _data_ptr, _data_len, NULL, 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, false, \ - true, NULL, NULL, NULL, NULL) + true, NULL, 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, false, \ - NULL, NULL, NULL, _ex_cb); \ + NULL, NULL, NULL, NULL, _ex_cb); \ ++_r_idx; \ } while (false) @@ -336,6 +337,7 @@ struct lwm2m_engine_res_inst { 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 validate_cb; lwm2m_engine_set_data_cb_t post_write_cb; lwm2m_engine_execute_cb_t execute_cb;