1 /*
2  * Copyright (c) 2024 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define LOG_MODULE_NAME app_fw_update
8 #define LOG_LEVEL LOG_LEVEL_DBG
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
11 
12 #include <zephyr/net/lwm2m.h>
13 #include <zephyr/sys/crc.h>
14 #include "lwm2m_engine.h"
15 
16 static uint8_t firmware_buf[64];
17 static uint32_t crc;
18 
19 /* Array with supported PULL firmware update protocols */
20 static uint8_t supported_protocol[1];
21 
firmware_update_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)22 static int firmware_update_cb(uint16_t obj_inst_id,
23 			      uint8_t *args, uint16_t args_len)
24 {
25 	LOG_INF("UPDATE, (CRC %u)", crc);
26 
27 	lwm2m_set_u8(&LWM2M_OBJ(5, 0, 3), STATE_IDLE);
28 	lwm2m_set_u8(&LWM2M_OBJ(5, 0, 5), RESULT_SUCCESS);
29 	return 0;
30 }
31 
firmware_get_buf(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,size_t * data_len)32 static void *firmware_get_buf(uint16_t obj_inst_id, uint16_t res_id,
33 			      uint16_t res_inst_id, size_t *data_len)
34 {
35 	*data_len = sizeof(firmware_buf);
36 	return firmware_buf;
37 }
38 
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)39 static int firmware_block_received_cb(uint16_t obj_inst_id, uint16_t res_id,
40 				      uint16_t res_inst_id, uint8_t *data,
41 				      uint16_t data_len, bool last_block,
42 				      size_t total_size, size_t offset)
43 {
44 	if (offset == 0) {
45 		crc = crc32_ieee(data, data_len);
46 	} else {
47 		crc = crc32_ieee_update(crc, data, data_len);
48 	}
49 	LOG_INF("FIRMWARE: BLOCK RECEIVED: offset:%zd len:%u last_block:%d crc: %u",
50 		offset, data_len, last_block, crc);
51 
52 	/* Add extra delay so short block-wise may timeout */
53 	k_sleep(K_MSEC(100));
54 	return 0;
55 }
56 
firmware_cancel_cb(const uint16_t obj_inst_id)57 static int firmware_cancel_cb(const uint16_t obj_inst_id)
58 {
59 	LOG_INF("FIRMWARE: Update canceled");
60 	return 0;
61 }
62 
init_firmware_update(void)63 static int init_firmware_update(void)
64 {
65 	/* setup data buffer for block-wise transfer */
66 	lwm2m_register_pre_write_callback(&LWM2M_OBJ(5, 0, 0), firmware_get_buf);
67 	lwm2m_firmware_set_write_cb(firmware_block_received_cb);
68 
69 	/* register cancel callback */
70 	lwm2m_firmware_set_cancel_cb(firmware_cancel_cb);
71 	lwm2m_firmware_set_update_cb(firmware_update_cb);
72 
73 	lwm2m_create_res_inst(&LWM2M_OBJ(5, 0, 8, 0));
74 	lwm2m_set_res_buf(&LWM2M_OBJ(5, 0, 8, 0), &supported_protocol[0],
75 					sizeof(supported_protocol[0]),
76 					sizeof(supported_protocol[0]), 0);
77 
78 	return 0;
79 }
80 LWM2M_APP_INIT(init_firmware_update);
81