net: lwm2m: Add offset to post-write callback

When Block-Wise transfer restarts, the post-write callback should
receive some indication that the block is actually a beginning of new,
instead of part of previous transfer.

Fixes #71351

Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
This commit is contained in:
Seppo Takalo 2024-05-10 13:35:11 +03:00 committed by Alberto Escolar
commit 01b57b4999
28 changed files with 122 additions and 87 deletions

View file

@ -378,6 +378,13 @@ Networking
``CONFIG_NET_TCP_RETRY_COUNT`` instead to control the total timeout at the
TCP level. (:github:`70731`)
* In LwM2M API, the callback type :c:type:`lwm2m_engine_set_data_cb_t` has now an additional
parameter ``offset``. This parameter is used to indicate the offset of the data
during a Coap Block-wise transfer. Any post write, validate or some firmware callbacks
should be updated to include this parameter. (:github:`72590`)
Other Subsystems
****************

View file

@ -287,6 +287,9 @@ Networking
* :c:func:`lwm2m_set_bulk`
* Added new ``offset`` parameter to :c:type:`lwm2m_engine_set_data_cb_t` callback type.
This affects post write and validate callbacks as well as some firmware callbacks.
* IPSP:
* Removed IPSP support. ``CONFIG_NET_L2_BT`` does not exist anymore.

View file

@ -329,6 +329,10 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id,
* make use of this callback to pass the data back to the client or LwM2M
* objects.
*
* On a block-wise transfers the handler is called multiple times with the data blocks
* and increasing offset. The last block has the last_block flag set to true.
* Beginning of the block transfer has the offset set to 0.
*
* A function of this type can be registered via:
* lwm2m_engine_register_validate_callback()
* lwm2m_engine_register_post_write_callback()
@ -344,6 +348,7 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id,
* false.
* @param[in] total_size Expected total size of data for a block transfer.
* For non-block transfers this is 0.
* @param[in] offset Offset of the data block. For non-block transfers this is always 0.
*
* @return Callback returns a negative error code (errno.h) indicating
* reason of failure or 0 for success.
@ -351,7 +356,7 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id,
typedef int (*lwm2m_engine_set_data_cb_t)(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size);
bool last_block, size_t total_size, size_t offset);
/**
* @brief Asynchronous event notification callback.

View file

@ -38,13 +38,13 @@ static void *firmware_get_buf(uint16_t obj_inst_id, uint16_t res_id,
return firmware_buf;
}
static int firmware_block_received_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int firmware_block_received_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
LOG_INF("FIRMWARE: BLOCK RECEIVED: len:%u last_block:%d",
data_len, last_block);
LOG_INF("FIRMWARE: BLOCK RECEIVED: offset:%zd len:%u last_block:%d",
offset, data_len, last_block);
return 0;
}

View file

@ -22,7 +22,7 @@ static uint32_t led_state;
/* TODO: Move to a pre write hook that can handle ret codes once available */
static int led_on_off_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block, size_t total_size)
uint16_t data_len, bool last_block, size_t total_size, size_t offset)
{
int ret = 0;
uint32_t led_val;

View file

@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
/* An example data validation callback. */
static int timer_on_off_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
LOG_INF("Validating On/Off data");
@ -34,7 +34,7 @@ static int timer_on_off_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint1
static int timer_digital_state_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
bool *digital_state = (bool *)data;

View file

@ -144,10 +144,10 @@ static int stop_buzzer(struct ipso_buzzer_data *buzzer, bool cancel)
return 0;
}
static int onoff_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int onoff_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;

View file

@ -112,7 +112,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id,
static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
int i;

View file

@ -121,7 +121,7 @@ static void update(uint16_t obj_inst_id, uint16_t res_id, int index)
static int update_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
bool last_block, size_t total_size, size_t offset)
{
int i;

View file

@ -121,7 +121,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id,
static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
int i;

View file

@ -107,7 +107,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id,
static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
int i;

View file

@ -88,10 +88,10 @@ static void *on_time_read_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res
return NULL;
}
static int on_time_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int on_time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;

View file

@ -87,10 +87,10 @@ static int get_switch_index(uint16_t obj_inst_id)
return ret;
}
static int state_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int state_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;
@ -157,10 +157,10 @@ static void *off_time_read_cb(uint16_t obj_inst_id,
return &switch_data[i].off_time_sec;
}
static int time_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i = get_switch_index(obj_inst_id);

View file

@ -108,7 +108,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id,
static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
int i;

View file

@ -82,10 +82,10 @@ static int get_button_index(uint16_t obj_inst_id)
return ret;
}
static int state_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int state_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;

View file

@ -107,10 +107,10 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id,
return -ENOENT;
}
static int sensor_value_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;

View file

@ -200,9 +200,10 @@ static void *cumulative_time_read_cb(uint16_t obj_inst_id,
}
static int cumulative_time_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;
@ -215,10 +216,10 @@ static int cumulative_time_post_write_cb(uint16_t obj_inst_id,
return 0;
}
static int enabled_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int enabled_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;
@ -236,9 +237,10 @@ static int enabled_post_write_cb(uint16_t obj_inst_id,
}
static int trigger_counter_post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;

View file

@ -113,7 +113,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id,
static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
int i;

View file

@ -984,7 +984,8 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst,
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);
last_pkt_block && last_block, opaque_ctx.len,
msg->in.block_ctx->ctx.current);
if (ret < 0) {
/* -EEXIST will generate Bad Request LWM2M response. */
return -EEXIST;
@ -997,11 +998,15 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst,
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_pkt_block && last_block, opaque_ctx.len);
last_pkt_block && last_block, opaque_ctx.len,
msg->in.block_ctx->ctx.current);
if (ret < 0) {
return ret;
}
}
if (msg->in.block_ctx) {
msg->in.block_ctx->ctx.current += len;
}
}
if (msg->in.block_ctx != NULL) {
@ -1200,11 +1205,13 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng
}
if (obj_field->data_type != LWM2M_RES_TYPE_OPAQUE) {
size_t offset = msg->in.block_ctx ? msg->in.block_ctx->ctx.current : 0;
#if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 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_block,
total_size);
total_size, offset);
if (ret < 0) {
/* -EEXIST will generate Bad Request LWM2M response. */
return -EEXIST;
@ -1227,7 +1234,7 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng
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);
total_size, offset);
}
}

View file

@ -335,8 +335,10 @@ static void add_existing_objects(void)
}
}
static int write_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len, bool last_block, size_t total_size)
static int write_validate_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
/* validates and removes acl instances for non-existing servers */

View file

@ -190,9 +190,9 @@ static void *current_time_pre_write_cb(uint16_t obj_inst_id, uint16_t res_id,
}
static int current_time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
if (data_len == 4U) {
time_offset = *(uint32_t *)data - k_uptime_seconds();

View file

@ -235,8 +235,9 @@ void lwm2m_firmware_set_update_result(uint8_t result)
}
static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
uint8_t state;
int ret = 0;
@ -270,7 +271,7 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id,
write_callback = lwm2m_firmware_get_write_cb_inst(obj_inst_id);
if (write_callback) {
ret = write_callback(obj_inst_id, res_id, res_inst_id, data, data_len, last_block,
total_size);
total_size, offset);
}
if (ret >= 0) {
@ -298,8 +299,9 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id,
}
static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
LOG_DBG("PACKAGE_URI WRITE: %s", package_uri[obj_inst_id]);

View file

@ -61,9 +61,10 @@ static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][GATEWAY_MAX_ID];
static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
lwm2m_engine_gateway_msg_cb gateway_msg_cb[MAX_INSTANCE_COUNT];
static int prefix_validation_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len, bool last_block,
size_t total_size)
static int prefix_validation_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int i;
int length;

View file

@ -146,7 +146,7 @@ bool lwm2m_server_get_mute_send(uint16_t obj_inst_id)
static int lifetime_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size)
size_t total_size, size_t offset)
{
ARG_UNUSED(obj_inst_id);
ARG_UNUSED(res_id);

View file

@ -187,9 +187,10 @@ static int callback_execute_not_defined(uint16_t obj_inst_id, uint8_t *args, uin
return -EINVAL;
}
static int callback_write_not_defined(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len, bool last_block,
size_t total_size)
static int callback_write_not_defined(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
LOG_ERR("Callback not defined for inst %u", obj_inst_id);
return -EINVAL;
@ -558,8 +559,10 @@ static int deactivate_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
return handle_event(instance, EVENT_DEACTIVATE);
}
static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len, bool last_block, size_t total_size)
static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
int ret = -EINVAL;
struct lwm2m_swmgmt_data *instance = NULL;
@ -643,9 +646,10 @@ static void set_update_result(uint16_t obj_inst_id, int error_code)
}
}
static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len, bool last_block,
size_t total_size)
static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
#ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
int error_code;

View file

@ -303,6 +303,8 @@ static int do_firmware_transfer_reply_cb(const struct coap_packet *response,
}
if (context.write_cb) {
size_t offset = context.block_ctx.current;
/* flush incoming data to write_cb */
while (payload_len > 0) {
len = (payload_len > write_buflen) ? write_buflen : payload_len;
@ -317,7 +319,8 @@ static int do_firmware_transfer_reply_cb(const struct coap_packet *response,
ret = context.write_cb(context.obj_inst_id, 0, 0, write_buf, len,
last_block && (payload_len == 0U),
context.block_ctx.total_size);
context.block_ctx.total_size, offset);
offset += len;
if (ret < 0) {
goto error;
}

View file

@ -668,7 +668,7 @@ static int lwm2m_engine_set(const struct lwm2m_obj_path *path, const void *value
#if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0
if (res->validate_cb) {
ret = res->validate_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id,
(uint8_t *)value, len, false, 0);
(uint8_t *)value, len, false, 0, 0);
if (ret < 0) {
k_mutex_unlock(&registry_lock);
return -EINVAL;
@ -774,7 +774,7 @@ static int lwm2m_engine_set(const struct lwm2m_obj_path *path, const void *value
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, false, 0);
data_ptr, len, false, 0, 0);
}
if (changed && LWM2M_HAS_PERM(obj_field, LWM2M_PERM_R)) {

View file

@ -23,10 +23,10 @@ static void *pre_write_cb(uint16_t obj_inst_id,
return pre_write_cb_buf;
}
static int post_write_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data,
uint16_t data_len, bool last_block,
size_t total_size, size_t offset)
{
callback_checker |= 0x02;
return 0;
@ -41,10 +41,9 @@ static void *read_cb(uint16_t obj_inst_id,
return 0;
}
static int validate_cb(uint16_t obj_inst_id,
uint16_t res_id, uint16_t res_inst_id,
uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size)
static int validate_cb(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, uint8_t *data, uint16_t data_len,
bool last_block, size_t total_size, size_t offset)
{
callback_checker |= 0x08;
return 0;