From d1a50eba63ac2f0ce09fcf52cba7dede28df3985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Tue, 26 Mar 2024 15:29:02 +0100 Subject: [PATCH] mgmt: hawkbit: use SMF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use smf for hawkbit. Signed-off-by: Fin Maaß --- include/zephyr/mgmt/hawkbit.h | 1 + samples/subsys/mgmt/hawkbit/prj.conf | 2 + subsys/mgmt/hawkbit/Kconfig | 2 + subsys/mgmt/hawkbit/hawkbit.c | 981 +++++++++++++++------------ subsys/mgmt/hawkbit/hawkbit_priv.h | 23 - 5 files changed, 553 insertions(+), 456 deletions(-) diff --git a/include/zephyr/mgmt/hawkbit.h b/include/zephyr/mgmt/hawkbit.h index f46b8bc7abc3e56..44a5b21932a7f12 100644 --- a/include/zephyr/mgmt/hawkbit.h +++ b/include/zephyr/mgmt/hawkbit.h @@ -30,6 +30,7 @@ enum hawkbit_response { HAWKBIT_PERMISSION_ERROR, HAWKBIT_METADATA_ERROR, HAWKBIT_DOWNLOAD_ERROR, + HAWKBIT_ALLOC_ERROR, HAWKBIT_OK, HAWKBIT_UPDATE_INSTALLED, HAWKBIT_NO_UPDATE, diff --git a/samples/subsys/mgmt/hawkbit/prj.conf b/samples/subsys/mgmt/hawkbit/prj.conf index 7b37086159df022..42951ec8b39d602 100644 --- a/samples/subsys/mgmt/hawkbit/prj.conf +++ b/samples/subsys/mgmt/hawkbit/prj.conf @@ -14,6 +14,8 @@ CONFIG_HTTP_CLIENT=y CONFIG_DNS_RESOLVER=y CONFIG_JSON_LIBRARY=y CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_SMF=y +CONFIG_SMF_ANCESTOR_SUPPORT=y #Main Stack Size CONFIG_MAIN_STACK_SIZE=4096 diff --git a/subsys/mgmt/hawkbit/Kconfig b/subsys/mgmt/hawkbit/Kconfig index 2621dde4a6dc58e..64ae78dfbd8d5b2 100644 --- a/subsys/mgmt/hawkbit/Kconfig +++ b/subsys/mgmt/hawkbit/Kconfig @@ -15,6 +15,8 @@ menuconfig HAWKBIT depends on DNS_RESOLVER depends on JSON_LIBRARY depends on BOOTLOADER_MCUBOOT + depends on SMF + depends on SMF_ANCESTOR_SUPPORT select EVENTS select MPU_ALLOW_FLASH_WRITE select IMG_ENABLE_IMAGE_CHECK diff --git a/subsys/mgmt/hawkbit/hawkbit.c b/subsys/mgmt/hawkbit/hawkbit.c index 505cb7c054999c6..4bc07a6970ee4b3 100644 --- a/subsys/mgmt/hawkbit/hawkbit.c +++ b/subsys/mgmt/hawkbit/hawkbit.c @@ -4,6 +4,7 @@ * Copyright (c) 2018 Foundries.io * Copyright (c) 2020 Linumiz * Copyright (c) 2021 G-Technologies Sdn. Bhd. + * Copyright (c) 2024 Vogl Electronic GmbH * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -71,26 +73,43 @@ struct hawkbit_download { uint8_t file_hash[SHA256_HASH_SIZE]; }; -static struct hawkbit_context { +union hawkbit_results { + struct hawkbit_dep_res dep; + struct hawkbit_ctl_res base; +}; + +struct hawkbit_context { int sock; - int32_t action_id; uint8_t *response_data; + size_t response_buffer_size; int32_t json_action_id; struct hawkbit_download dl; - struct http_request http_req; struct flash_img_context flash_ctx; - uint8_t url_buffer[URL_BUFFER_SIZE]; - uint8_t status_buffer[STATUS_BUFFER_SIZE]; - uint8_t recv_buf_tcp[RECV_BUFFER_SIZE]; enum hawkbit_response code_status; bool final_data_received; -} hb_context; + enum hawkbit_http_request type; + union hawkbit_results results; +}; -static union { - struct hawkbit_dep_res dep; - struct hawkbit_ctl_res base; - struct hawkbit_cancel cancel; -} hawkbit_results; +struct s_object { + struct smf_ctx ctx; + struct hawkbit_context hb_context; + char device_id[DEVICE_ID_HEX_MAX_SIZE]; +}; + +static const struct smf_state hawkbit_states[]; + +enum hawkbit_state { + S_HAWKBIT_START, + S_HAWKBIT_HTTP, + S_HAWKBIT_RESPONSE_DATA, + S_HAWKBIT_PROBE, + S_HAWKBIT_CONFIG_DEVICE, + S_HAWKBIT_CLOSE, + S_HAWKBIT_PROBE_DEPLOYMENT_BASE, + S_HAWKBIT_REPORT, + S_HAWKBIT_DOWNLOAD, +}; static void autohandler(struct k_work *work); @@ -192,7 +211,7 @@ static const struct json_obj_descr json_dep_fbk_descr[] = { JSON_OBJ_DESCR_OBJECT(struct hawkbit_dep_fbk, status, json_status_descr), }; -static bool start_http_client(void) +static bool start_http_client(int *hb_sock) { int ret = -1; struct zsock_addrinfo *addr; @@ -222,8 +241,8 @@ static bool start_http_client(void) return false; } - hb_context.sock = zsock_socket(addr->ai_family, SOCK_STREAM, protocol); - if (hb_context.sock < 0) { + *hb_sock = zsock_socket(addr->ai_family, SOCK_STREAM, protocol); + if (*hb_sock < 0) { LOG_ERR("Failed to create TCP socket"); goto err; } @@ -233,19 +252,19 @@ static bool start_http_client(void) CA_CERTIFICATE_TAG, }; - if (zsock_setsockopt(hb_context.sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, + if (zsock_setsockopt(*hb_sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt)) < 0) { LOG_ERR("Failed to set TLS_TAG option"); goto err_sock; } - if (zsock_setsockopt(hb_context.sock, SOL_TLS, TLS_HOSTNAME, CONFIG_HAWKBIT_SERVER, + if (zsock_setsockopt(*hb_sock, SOL_TLS, TLS_HOSTNAME, CONFIG_HAWKBIT_SERVER, sizeof(CONFIG_HAWKBIT_SERVER)) < 0) { goto err_sock; } #endif - if (zsock_connect(hb_context.sock, addr->ai_addr, addr->ai_addrlen) < 0) { + if (zsock_connect(*hb_sock, addr->ai_addr, addr->ai_addrlen) < 0) { LOG_ERR("Failed to connect to server"); goto err_sock; } @@ -254,15 +273,15 @@ static bool start_http_client(void) return true; err_sock: - zsock_close(hb_context.sock); + zsock_close(*hb_sock); err: zsock_freeaddrinfo(addr); return false; } -static void cleanup_connection(void) +static void cleanup_connection(int *hb_sock) { - if (zsock_close(hb_context.sock) < 0) { + if (zsock_close(*hb_sock) < 0) { LOG_ERR("Failed to close the socket"); } } @@ -357,7 +376,9 @@ static void hawkbit_update_sleep(struct hawkbit_ctl_res *hawkbit_res) /* * Find URL component for the device cancel operation and action id */ -static int hawkbit_find_cancelAction_base(struct hawkbit_ctl_res *res, char *cancel_base) +static int hawkbit_find_cancelAction_base(struct hawkbit_context *hb_context, + struct hawkbit_ctl_res *res, char *cancel_base, + int32_t *cancel_action_id) { size_t len; const char *href; @@ -398,9 +419,9 @@ static int hawkbit_find_cancelAction_base(struct hawkbit_ctl_res *res, char *can return -EINVAL; } - hb_context.action_id = strtol(helper, &endptr, 10); - if (hb_context.action_id <= 0) { - LOG_ERR("Invalid action_id: %d", hb_context.action_id); + *cancel_action_id = strtol(helper, &endptr, 10); + if (*cancel_action_id <= 0) { + LOG_ERR("Invalid action_id: %d", *cancel_action_id); return -EINVAL; } @@ -444,29 +465,35 @@ static int hawkbit_find_deployment_base(struct hawkbit_ctl_res *res, char *deplo return 0; } +static int hawkbit_deployment_get_action_id(struct hawkbit_dep_res *res, int32_t *action_id) +{ + int32_t id; + + id = strtol(res->id, NULL, 10); + if (id <= 0) { + LOG_ERR("Invalid action_id: %d", id); + return -EINVAL; + } + + *action_id = id; + + return 0; +} + /* * Find URL component for this device's deployment operations * resource. */ -static int hawkbit_parse_deployment(struct hawkbit_dep_res *res, int32_t *json_action_id, +static int hawkbit_parse_deployment(struct hawkbit_context *hb_context, struct hawkbit_dep_res *res, char *download_http, int32_t *file_size) { int32_t size; - char *endptr; const char *href; const char *helper; struct hawkbit_dep_res_chunk *chunk; size_t len, num_chunks, num_artifacts; struct hawkbit_dep_res_arts *artifact; - hb_context.action_id = strtol(res->id, &endptr, 10); - if (hb_context.action_id < 0) { - LOG_ERR("Invalid action_id: %d", hb_context.action_id); - return -EINVAL; - } - - *json_action_id = hb_context.action_id; - num_chunks = res->deployment.num_chunks; if (num_chunks != 1) { LOG_ERR("Expecting 1 chunk (got %d)", num_chunks); @@ -486,8 +513,8 @@ static int hawkbit_parse_deployment(struct hawkbit_dep_res *res, int32_t *json_a } artifact = &chunk->artifacts[0]; - if (hex2bin(artifact->hashes.sha256, SHA256_HASH_SIZE << 1, hb_context.dl.file_hash, - sizeof(hb_context.dl.file_hash)) != SHA256_HASH_SIZE) { + if (hex2bin(artifact->hashes.sha256, SHA256_HASH_SIZE << 1, hb_context->dl.file_hash, + sizeof(hb_context->dl.file_hash)) != SHA256_HASH_SIZE) { return -EINVAL; } @@ -525,8 +552,12 @@ static int hawkbit_parse_deployment(struct hawkbit_dep_res *res, int32_t *json_a } /* Success. */ - strncpy(download_http, helper, DOWNLOAD_HTTP_SIZE); - *file_size = size; + if (download_http != NULL) { + strncpy(download_http, helper, DOWNLOAD_HTTP_SIZE); + } + if (file_size != NULL) { + *file_size = size; + } return 0; } @@ -605,178 +636,133 @@ int hawkbit_init(void) return ret; } -static int enum_for_http_req_string(char *userdata) -{ - int i = 0; - char *name = http_request[i].http_req_str; - - while (name) { - if (strcmp(name, userdata) == 0) { - return http_request[i].n; - } - - name = http_request[++i].http_req_str; - } - - return 0; -} - static void response_cb(struct http_response *rsp, enum http_final_call final_data, void *userdata) { - static size_t body_len; - int ret, type, downloaded; + struct hawkbit_context *hb_context = userdata; + size_t body_len; + int ret, downloaded; uint8_t *body_data = NULL, *rsp_tmp = NULL; - static size_t response_buffer_size = RESPONSE_BUFFER_SIZE; - - type = enum_for_http_req_string(userdata); if (rsp->http_status_code != 200) { - LOG_ERR("HTTP request denied (%s): %d", (char *)userdata, rsp->http_status_code); + LOG_ERR("HTTP request denied: %d", rsp->http_status_code); if (rsp->http_status_code == 401 || rsp->http_status_code == 403) { - hb_context.code_status = HAWKBIT_PERMISSION_ERROR; + hb_context->code_status = HAWKBIT_PERMISSION_ERROR; } else { - hb_context.code_status = HAWKBIT_METADATA_ERROR; + hb_context->code_status = HAWKBIT_METADATA_ERROR; } return; } - switch (type) { + switch (hb_context->type) { case HAWKBIT_PROBE: - if (hb_context.dl.http_content_size == 0) { - hb_context.dl.http_content_size = rsp->content_length; - } - - if (rsp->body_found) { - body_data = rsp->body_frag_start; - body_len = rsp->body_frag_len; - - if ((hb_context.dl.downloaded_size + body_len) > response_buffer_size) { - response_buffer_size <<= 1; - rsp_tmp = realloc(hb_context.response_data, response_buffer_size); - if (rsp_tmp == NULL) { - LOG_ERR("Failed to realloc memory"); - hb_context.code_status = HAWKBIT_METADATA_ERROR; - break; - } - - hb_context.response_data = rsp_tmp; - } - strncpy(hb_context.response_data + hb_context.dl.downloaded_size, body_data, - body_len); - hb_context.dl.downloaded_size += body_len; - } - - if (final_data == HTTP_DATA_FINAL) { - if (hb_context.dl.http_content_size != hb_context.dl.downloaded_size) { - LOG_ERR("HTTP response len mismatch, expected %d, got %d", - hb_context.dl.http_content_size, - hb_context.dl.downloaded_size); - hb_context.code_status = HAWKBIT_METADATA_ERROR; - break; - } - - hb_context.response_data[hb_context.dl.downloaded_size] = '\0'; - ret = json_obj_parse(hb_context.response_data, - hb_context.dl.downloaded_size, json_ctl_res_descr, - ARRAY_SIZE(json_ctl_res_descr), &hawkbit_results.base); - if (ret < 0) { - LOG_ERR("JSON parse error (%s): %d", "HAWKBIT_PROBE", ret); - hb_context.code_status = HAWKBIT_METADATA_ERROR; - } - } - - break; - - case HAWKBIT_CLOSE: - case HAWKBIT_REPORT: - case HAWKBIT_CONFIG_DEVICE: - break; - case HAWKBIT_PROBE_DEPLOYMENT_BASE: - if (hb_context.dl.http_content_size == 0) { - hb_context.dl.http_content_size = rsp->content_length; + if (hb_context->dl.http_content_size == 0) { + hb_context->dl.http_content_size = rsp->content_length; } if (rsp->body_found) { body_data = rsp->body_frag_start; body_len = rsp->body_frag_len; - if ((hb_context.dl.downloaded_size + body_len) > response_buffer_size) { - response_buffer_size <<= 1; - rsp_tmp = realloc(hb_context.response_data, response_buffer_size); + if ((hb_context->dl.downloaded_size + body_len) > + hb_context->response_buffer_size) { + hb_context->response_buffer_size = + hb_context->dl.downloaded_size + body_len; + rsp_tmp = realloc(hb_context->response_data, + hb_context->response_buffer_size); if (rsp_tmp == NULL) { LOG_ERR("Failed to realloc memory"); - hb_context.code_status = HAWKBIT_METADATA_ERROR; + hb_context->code_status = HAWKBIT_ALLOC_ERROR; break; } - hb_context.response_data = rsp_tmp; + hb_context->response_data = rsp_tmp; } - strncpy(hb_context.response_data + hb_context.dl.downloaded_size, body_data, - body_len); - hb_context.dl.downloaded_size += body_len; + strncpy(hb_context->response_data + hb_context->dl.downloaded_size, + body_data, body_len); + hb_context->dl.downloaded_size += body_len; } if (final_data == HTTP_DATA_FINAL) { - if (hb_context.dl.http_content_size != hb_context.dl.downloaded_size) { + if (hb_context->dl.http_content_size != hb_context->dl.downloaded_size) { LOG_ERR("HTTP response len mismatch, expected %d, got %d", - hb_context.dl.http_content_size, - hb_context.dl.downloaded_size); - hb_context.code_status = HAWKBIT_METADATA_ERROR; + hb_context->dl.http_content_size, + hb_context->dl.downloaded_size); + hb_context->code_status = HAWKBIT_METADATA_ERROR; break; } - hb_context.response_data[hb_context.dl.downloaded_size] = '\0'; - ret = json_obj_parse(hb_context.response_data, - hb_context.dl.downloaded_size, json_dep_res_descr, - ARRAY_SIZE(json_dep_res_descr), &hawkbit_results.dep); - if (ret < 0) { - LOG_ERR("JSON parse error (%s): %d", "deploymentBase", ret); - hb_context.code_status = HAWKBIT_METADATA_ERROR; + hb_context->response_data[hb_context->dl.downloaded_size] = '\0'; + memset(&hb_context->results, 0, sizeof(hb_context->results)); + if (hb_context->type == HAWKBIT_PROBE) { + ret = json_obj_parse( + hb_context->response_data, hb_context->dl.downloaded_size, + json_ctl_res_descr, ARRAY_SIZE(json_ctl_res_descr), + &hb_context->results.base); + if (ret < 0) { + LOG_ERR("JSON parse error (%s): %d", "HAWKBIT_PROBE", ret); + hb_context->code_status = HAWKBIT_METADATA_ERROR; + } + } else { + ret = json_obj_parse( + hb_context->response_data, hb_context->dl.downloaded_size, + json_dep_res_descr, ARRAY_SIZE(json_dep_res_descr), + &hb_context->results.dep); + if (ret < 0) { + LOG_ERR("JSON parse error (%s): %d", "deploymentBase", ret); + hb_context->code_status = HAWKBIT_METADATA_ERROR; + } } } break; case HAWKBIT_DOWNLOAD: - if (hb_context.dl.http_content_size == 0) { - hb_context.dl.http_content_size = rsp->content_length; + if (hb_context->dl.http_content_size == 0) { + hb_context->dl.http_content_size = rsp->content_length; } if (rsp->body_found) { body_data = rsp->body_frag_start; body_len = rsp->body_frag_len; - ret = flash_img_buffered_write(&hb_context.flash_ctx, body_data, body_len, + ret = flash_img_buffered_write(&hb_context->flash_ctx, body_data, body_len, final_data == HTTP_DATA_FINAL); if (ret < 0) { LOG_ERR("Failed to write flash: %d", ret); - hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; + hb_context->code_status = HAWKBIT_DOWNLOAD_ERROR; break; } } - hb_context.dl.downloaded_size = flash_img_bytes_written(&hb_context.flash_ctx); + hb_context->dl.downloaded_size = flash_img_bytes_written(&hb_context->flash_ctx); - downloaded = hb_context.dl.downloaded_size * 100 / hb_context.dl.http_content_size; + downloaded = + hb_context->dl.downloaded_size * 100 / hb_context->dl.http_content_size; - if (downloaded > hb_context.dl.download_progress) { - hb_context.dl.download_progress = downloaded; - LOG_DBG("Downloaded: %d%% ", hb_context.dl.download_progress); + if (downloaded > hb_context->dl.download_progress) { + hb_context->dl.download_progress = downloaded; + LOG_DBG("Downloaded: %d%% ", hb_context->dl.download_progress); } if (final_data == HTTP_DATA_FINAL) { - hb_context.final_data_received = true; + hb_context->final_data_received = true; } + break; + + default: + break; } } -static bool send_request(enum http_method method, enum hawkbit_http_request type, - enum hawkbit_status_fini finished, enum hawkbit_status_exec execution) +static bool send_request(struct hawkbit_context *hb_context, enum hawkbit_http_request type, + uint8_t *url_buffer, uint8_t *status_buffer) { int ret = 0; + uint8_t recv_buf_tcp[RECV_BUFFER_SIZE] = {0}; + struct http_request http_req = {0}; #ifndef CONFIG_HAWKBIT_DDI_NO_SECURITY static const char *const headers[] = { #ifdef CONFIG_HAWKBIT_DDI_GATEWAY_SECURITY @@ -788,173 +774,81 @@ static bool send_request(enum http_method method, enum hawkbit_http_request type }; #endif /* CONFIG_HAWKBIT_DDI_NO_SECURITY */ - memset(&hb_context.http_req, 0, sizeof(hb_context.http_req)); - memset(&hb_context.recv_buf_tcp, 0, sizeof(hb_context.recv_buf_tcp)); - hb_context.http_req.url = hb_context.url_buffer; - hb_context.http_req.method = method; - hb_context.http_req.host = CONFIG_HAWKBIT_SERVER; - hb_context.http_req.port = CONFIG_HAWKBIT_PORT; - hb_context.http_req.protocol = "HTTP/1.1"; - hb_context.http_req.response = response_cb; - hb_context.http_req.recv_buf = hb_context.recv_buf_tcp; - hb_context.http_req.recv_buf_len = sizeof(hb_context.recv_buf_tcp); + http_req.url = url_buffer; + http_req.host = CONFIG_HAWKBIT_SERVER; + http_req.port = CONFIG_HAWKBIT_PORT; + http_req.protocol = "HTTP/1.1"; + http_req.response = response_cb; + http_req.recv_buf = recv_buf_tcp; + http_req.recv_buf_len = sizeof(recv_buf_tcp); #ifndef CONFIG_HAWKBIT_DDI_NO_SECURITY - hb_context.http_req.header_fields = (const char **)headers; + http_req.header_fields = (const char **)headers; #endif - hb_context.final_data_received = false; + hb_context->final_data_received = false; + hb_context->type = type; switch (type) { - case HAWKBIT_PROBE: - /* - * Root resource for an individual Target - * GET: /{tenant}/controller/v1/{controllerId} - */ - ret = http_client_req(hb_context.sock, &hb_context.http_req, HAWKBIT_RECV_TIMEOUT, - "HAWKBIT_PROBE"); - if (ret < 0) { - LOG_ERR("Unable to send HTTP request (%s): %d", "HAWKBIT_PROBE", ret); - return false; - } - - break; - case HAWKBIT_CONFIG_DEVICE: /* * Feedback channel for the config data action - * POST: /{tenant}/controller/v1/{controllerId}/configData + * PUT: /default/controller/v1/{controllerId}/configData */ - char device_id[DEVICE_ID_HEX_MAX_SIZE] = {0}; - - if (!hawkbit_get_device_identity(device_id, DEVICE_ID_HEX_MAX_SIZE)) { - hb_context.code_status = HAWKBIT_METADATA_ERROR; - } - - struct hawkbit_cfg cfg = { - .mode = "merge", - .data.VIN = device_id, - }; - - ret = json_obj_encode_buf(json_cfg_descr, ARRAY_SIZE(json_cfg_descr), &cfg, - hb_context.status_buffer, - sizeof(hb_context.status_buffer)); - if (ret) { - LOG_ERR("Can't encode the JSON script (%s): %d", "HAWKBIT_CONFIG_DEVICE", - ret); - return false; - } - - hb_context.http_req.content_type_value = HTTP_HEADER_CONTENT_TYPE_JSON; - hb_context.http_req.payload = hb_context.status_buffer; - hb_context.http_req.payload_len = strlen(hb_context.status_buffer); - - ret = http_client_req(hb_context.sock, &hb_context.http_req, HAWKBIT_RECV_TIMEOUT, - "HAWKBIT_CONFIG_DEVICE"); - if (ret < 0) { - LOG_ERR("Unable to send HTTP request (%s): %d", "HAWKBIT_CONFIG_DEVICE", - ret); - return false; - } + http_req.method = HTTP_PUT; + http_req.content_type_value = HTTP_HEADER_CONTENT_TYPE_JSON; + http_req.payload = status_buffer; + http_req.payload_len = strlen(status_buffer); break; case HAWKBIT_CLOSE: /* * Feedback channel for cancel actions - * POST: /{tenant}/controller/v1/{controllerId}/cancelAction/{actionId}/feedback + * POST: /default/controller/v1/{controllerId}/cancelAction/{actionId}/feedback */ - struct hawkbit_close close = { - .status.execution = hawkbit_status_execution(execution), - .status.result.finished = hawkbit_status_finished(finished), - }; - - ret = json_obj_encode_buf(json_close_descr, ARRAY_SIZE(json_close_descr), &close, - hb_context.status_buffer, - sizeof(hb_context.status_buffer)); - if (ret) { - LOG_ERR("Can't encode the JSON script (%s): %d", "HAWKBIT_CLOSE", ret); - return false; - } - - hb_context.http_req.content_type_value = HTTP_HEADER_CONTENT_TYPE_JSON; - hb_context.http_req.payload = hb_context.status_buffer; - hb_context.http_req.payload_len = strlen(hb_context.status_buffer); - - ret = http_client_req(hb_context.sock, &hb_context.http_req, HAWKBIT_RECV_TIMEOUT, - "HAWKBIT_CLOSE"); - if (ret < 0) { - LOG_ERR("Unable to send HTTP request (%s): %d", "HAWKBIT_CLOSE", ret); - return false; - } + case HAWKBIT_REPORT: + /* + * Feedback channel for the DeploymentBase action + * POST: /default/controller/v1/{controllerId}/deploymentBase/{actionId}/feedback + */ + http_req.method = HTTP_POST; + http_req.content_type_value = HTTP_HEADER_CONTENT_TYPE_JSON; + http_req.payload = status_buffer; + http_req.payload_len = strlen(status_buffer); break; + case HAWKBIT_PROBE: + /* + * Root resource for an individual Target + * GET: /default/controller/v1/{controllerId} + */ case HAWKBIT_PROBE_DEPLOYMENT_BASE: /* * Resource for software module (Deployment Base) - * GET: /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId} + * GET: /default/controller/v1/{controllerId}/deploymentBase/{actionId} */ - hb_context.http_req.content_type_value = NULL; - ret = http_client_req(hb_context.sock, &hb_context.http_req, HAWKBIT_RECV_TIMEOUT, - "HAWKBIT_PROBE_DEPLOYMENT_BASE"); - if (ret < 0) { - LOG_ERR("Unable to send HTTP request (%s): %d", - "HAWKBIT_PROBE_DEPLOYMENT_BASE", ret); - return false; - } - - break; - - case HAWKBIT_REPORT: + case HAWKBIT_DOWNLOAD: /* - * Feedback channel for the DeploymentBase action - * POST: /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId}/feedback + * Artifact download + * GET: /default/controller/v1/{controllerId}/softwaremodules/{softwareModuleId} + * /artifacts/{fileName} */ - const char *fini = hawkbit_status_finished(finished); - const char *exec = hawkbit_status_execution(execution); - - LOG_INF("Reporting deployment feedback %s (%s) for action %d", fini, exec, - hb_context.json_action_id); - - struct hawkbit_dep_fbk feedback = { - .status.execution = exec, - .status.result.finished = fini, - }; - - ret = json_obj_encode_buf(json_dep_fbk_descr, ARRAY_SIZE(json_dep_fbk_descr), - &feedback, hb_context.status_buffer, - sizeof(hb_context.status_buffer)); - if (ret) { - LOG_ERR("Can't encode the JSON script (%s): %d", "HAWKBIT_REPORT", ret); - return ret; - } - - hb_context.http_req.content_type_value = HTTP_HEADER_CONTENT_TYPE_JSON; - hb_context.http_req.payload = hb_context.status_buffer; - hb_context.http_req.payload_len = strlen(hb_context.status_buffer); - - ret = http_client_req(hb_context.sock, &hb_context.http_req, HAWKBIT_RECV_TIMEOUT, - "HAWKBIT_REPORT"); - if (ret < 0) { - LOG_ERR("Unable to send HTTP request (%s): %d", "HAWKBIT_REPORT", ret); - return false; - } + http_req.method = HTTP_GET; + hb_context->dl.http_content_size = 0; + hb_context->dl.downloaded_size = 0; break; - case HAWKBIT_DOWNLOAD: - /* - * Resource for software module (Deployment Base) - * GET: /{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/ - * artifacts/{fileName} - */ - ret = http_client_req(hb_context.sock, &hb_context.http_req, HAWKBIT_RECV_TIMEOUT, - "HAWKBIT_DOWNLOAD"); - if (ret < 0) { - LOG_ERR("Unable to send HTTP request (%s): %d", "HAWKBIT_DOWNLOAD", ret); - return false; - } + default: + return false; + } - break; + ret = http_client_req(hb_context->sock, &http_req, HAWKBIT_RECV_TIMEOUT, + hb_context); + if (ret < 0) { + LOG_ERR("Failed to send request: %d", ret); + hb_context->code_status = HAWKBIT_NETWORKING_ERROR; + return false; } return true; @@ -966,230 +860,447 @@ void hawkbit_reboot(void) sys_reboot(SYS_REBOOT_WARM); } -enum hawkbit_response hawkbit_probe(void) +static void s_start(void *o) { - int ret; - int32_t action_id; - int32_t file_size = 0; - struct flash_img_check fic; - char device_id[DEVICE_ID_HEX_MAX_SIZE] = { 0 }, - cancel_base[CANCEL_BASE_SIZE] = { 0 }, - download_http[DOWNLOAD_HTTP_SIZE] = { 0 }, - deployment_base[DEPLOYMENT_BASE_SIZE] = { 0 }, - firmware_version[BOOT_IMG_VER_STRLEN_MAX] = { 0 }; + struct s_object *s = (struct s_object *)o; if (k_sem_take(&probe_sem, K_NO_WAIT) != 0) { - return HAWKBIT_PROBE_IN_PROGRESS; + LOG_INF("hawkBit is already running"); + smf_set_terminate(SMF_CTX(s), HAWKBIT_PROBE_IN_PROGRESS); + return; } - memset(&hb_context, 0, sizeof(hb_context)); - hb_context.response_data = malloc(RESPONSE_BUFFER_SIZE); - if (!boot_is_img_confirmed()) { LOG_ERR("Current image is not confirmed"); - hb_context.code_status = HAWKBIT_UNCONFIRMED_IMAGE; - goto error; + k_sem_give(&probe_sem); + smf_set_terminate(SMF_CTX(s), HAWKBIT_UNCONFIRMED_IMAGE); + return; } - if (!hawkbit_get_firmware_version(firmware_version, BOOT_IMG_VER_STRLEN_MAX)) { - hb_context.code_status = HAWKBIT_METADATA_ERROR; - goto error; + if (!hawkbit_get_device_identity(s->device_id, DEVICE_ID_HEX_MAX_SIZE)) { + k_sem_give(&probe_sem); + smf_set_terminate(SMF_CTX(s), HAWKBIT_METADATA_ERROR); + return; } +} - if (!hawkbit_get_device_identity(device_id, DEVICE_ID_HEX_MAX_SIZE)) { - hb_context.code_status = HAWKBIT_METADATA_ERROR; - goto error; +static void s_end(void *o) +{ + struct s_object *s = (struct s_object *)o; + + k_sem_give(&probe_sem); + smf_set_terminate(SMF_CTX(s), s->hb_context.code_status); +} + +static void s_http_start(void *o) +{ + struct s_object *s = (struct s_object *)o; + + if (!start_http_client(&s->hb_context.sock)) { + s->hb_context.code_status = HAWKBIT_NETWORKING_ERROR; + smf_set_state(SMF_CTX(s), NULL); } +} - if (!start_http_client()) { - hb_context.code_status = HAWKBIT_NETWORKING_ERROR; - goto error; +static void s_http_end(void *o) +{ + struct s_object *s = (struct s_object *)o; + + cleanup_connection(&s->hb_context.sock); +} + +static void s_response_data_start(void *o) +{ + struct s_object *s = (struct s_object *)o; + + s->hb_context.response_buffer_size = RESPONSE_BUFFER_SIZE; + + s->hb_context.response_data = calloc(s->hb_context.response_buffer_size, sizeof(uint8_t)); + if (s->hb_context.response_data == NULL) { + s->hb_context.code_status = HAWKBIT_ALLOC_ERROR; + smf_set_state(SMF_CTX(s), NULL); } +} + +static void s_response_data_end(void *o) +{ + struct s_object *s = (struct s_object *)o; + + free(s->hb_context.response_data); +} + +/* + * Root resource for an individual Target + * GET: /default/controller/v1/{controllerId} + */ +static void s_probe(void *o) +{ + struct s_object *s = (struct s_object *)o; - /* - * Query the hawkBit base polling resource. - */ LOG_INF("Polling target data from hawkBit"); - memset(hb_context.url_buffer, 0, sizeof(hb_context.url_buffer)); - hb_context.dl.http_content_size = 0; - hb_context.dl.downloaded_size = 0; - snprintk(hb_context.url_buffer, sizeof(hb_context.url_buffer), "%s/%s-%s", - HAWKBIT_JSON_URL, CONFIG_BOARD, device_id); - memset(&hawkbit_results.base, 0, sizeof(hawkbit_results.base)); + uint8_t url_buffer[URL_BUFFER_SIZE] = {0}; - if (!send_request(HTTP_GET, HAWKBIT_PROBE, HAWKBIT_STATUS_FINISHED_NONE, - HAWKBIT_STATUS_EXEC_NONE)) { + snprintk(url_buffer, sizeof(url_buffer), "%s/%s-%s", HAWKBIT_JSON_URL, CONFIG_BOARD, + s->device_id); + + if (!send_request(&s->hb_context, HAWKBIT_PROBE, url_buffer, NULL)) { LOG_ERR("Send request failed (%s)", "HAWKBIT_PROBE"); - hb_context.code_status = HAWKBIT_NETWORKING_ERROR; - goto cleanup; + smf_set_state(SMF_CTX(s), NULL); + return; } - if (hb_context.code_status == HAWKBIT_METADATA_ERROR || - hb_context.code_status == HAWKBIT_PERMISSION_ERROR) { - goto cleanup; + if (s->hb_context.code_status == HAWKBIT_METADATA_ERROR || + s->hb_context.code_status == HAWKBIT_PERMISSION_ERROR) { + smf_set_state(SMF_CTX(s), NULL); + return; } - if (hawkbit_results.base.config.polling.sleep) { + if (s->hb_context.results.base.config.polling.sleep) { /* Update the sleep time. */ - hawkbit_update_sleep(&hawkbit_results.base); - LOG_DBG("config.polling.sleep=%s", hawkbit_results.base.config.polling.sleep); + LOG_DBG("config.polling.sleep=%s", s->hb_context.results.base.config.polling.sleep); + hawkbit_update_sleep(&s->hb_context.results.base); } + if (s->hb_context.results.base._links.cancelAction.href) { + LOG_DBG("_links.%s.href=%s", "cancelAction", + s->hb_context.results.base._links.cancelAction.href); + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_CLOSE]); + return; + } - if (hawkbit_results.base._links.cancelAction.href) { - ret = hawkbit_find_cancelAction_base(&hawkbit_results.base, cancel_base); - memset(hb_context.url_buffer, 0, sizeof(hb_context.url_buffer)); - hb_context.dl.http_content_size = 0; - snprintk(hb_context.url_buffer, sizeof(hb_context.url_buffer), - "%s/%s-%s/%s/feedback", HAWKBIT_JSON_URL, CONFIG_BOARD, device_id, - cancel_base); - memset(&hawkbit_results.cancel, 0, sizeof(hawkbit_results.cancel)); + if (s->hb_context.results.base._links.configData.href) { + LOG_DBG("_links.%s.href=%s", "configData", + s->hb_context.results.base._links.configData.href); + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_CONFIG_DEVICE]); + return; + } - if (!send_request(HTTP_POST, HAWKBIT_CLOSE, HAWKBIT_STATUS_FINISHED_SUCCESS, - HAWKBIT_STATUS_EXEC_CLOSED)) { - LOG_ERR("Send request failed (%s)", "HAWKBIT_CLOSE"); - hb_context.code_status = HAWKBIT_NETWORKING_ERROR; - goto cleanup; - } + if (s->hb_context.results.base._links.deploymentBase.href) { + LOG_DBG("_links.%s.href=%s", "deploymentBase", + s->hb_context.results.base._links.deploymentBase.href); + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_PROBE_DEPLOYMENT_BASE]); + return; + } + + s->hb_context.code_status = HAWKBIT_NO_UPDATE; + smf_set_state(SMF_CTX(s), NULL); +} - hb_context.code_status = HAWKBIT_CANCEL_UPDATE; - goto cleanup; +/* + * Feedback channel for cancel actions + * POST: /default/controller/v1/{controllerId}/cancelAction/{actionId}/feedback + */ +static void s_hawbit_close(void *o) +{ + int ret = 0; + int32_t action_id = 0; + int32_t cancel_action_id = 0; + struct s_object *s = (struct s_object *)o; + char cancel_base[CANCEL_BASE_SIZE] = {0}; + uint8_t status_buffer[STATUS_BUFFER_SIZE] = {0}; + uint8_t url_buffer[URL_BUFFER_SIZE] = {0}; + + ret = hawkbit_find_cancelAction_base(&s->hb_context, &s->hb_context.results.base, + cancel_base, &cancel_action_id); + if (ret < 0) { + LOG_ERR("Can't find cancelAction base: %d", ret); + s->hb_context.code_status = HAWKBIT_METADATA_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; } - if (hawkbit_results.base._links.configData.href) { - LOG_DBG("_links.%s.href=%s", "configData", - hawkbit_results.base._links.configData.href); - memset(hb_context.url_buffer, 0, sizeof(hb_context.url_buffer)); - hb_context.dl.http_content_size = 0; - snprintk(hb_context.url_buffer, sizeof(hb_context.url_buffer), "%s/%s-%s/%s", - HAWKBIT_JSON_URL, CONFIG_BOARD, device_id, "configData"); - - if (!send_request(HTTP_PUT, HAWKBIT_CONFIG_DEVICE, HAWKBIT_STATUS_FINISHED_SUCCESS, - HAWKBIT_STATUS_EXEC_CLOSED)) { - LOG_ERR("Send request failed (%s)", "HAWKBIT_CONFIG_DEVICE"); - hb_context.code_status = HAWKBIT_NETWORKING_ERROR; - goto cleanup; - } + snprintk(url_buffer, sizeof(url_buffer), "%s/%s-%s/%s/%s", HAWKBIT_JSON_URL, CONFIG_BOARD, + s->device_id, cancel_base, "feedback"); + + nvs_read(&fs, ADDRESS_ID, &action_id, sizeof(action_id)); + + struct hawkbit_close close = { + .status.execution = hawkbit_status_execution(HAWKBIT_STATUS_EXEC_CLOSED), + .status.result.finished = hawkbit_status_finished( + action_id == cancel_action_id ? HAWKBIT_STATUS_FINISHED_FAILURE + : HAWKBIT_STATUS_FINISHED_SUCCESS), + }; + + ret = json_obj_encode_buf(json_close_descr, ARRAY_SIZE(json_close_descr), &close, + status_buffer, sizeof(status_buffer)); + if (ret) { + LOG_ERR("Can't encode the JSON script (%s): %d", "HAWKBIT_CLOSE", ret); + s->hb_context.code_status = HAWKBIT_METADATA_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; } - ret = hawkbit_find_deployment_base(&hawkbit_results.base, deployment_base); - if (ret < 0) { - hb_context.code_status = HAWKBIT_METADATA_ERROR; - LOG_ERR("Unable to find URL for the device's deploymentBase: %d", ret); - goto cleanup; + if (!send_request(&s->hb_context, HAWKBIT_CLOSE, url_buffer, status_buffer)) { + LOG_ERR("Send request failed (%s)", "HAWKBIT_CLOSE"); + } else { + s->hb_context.code_status = HAWKBIT_CANCEL_UPDATE; } - if (strlen(deployment_base) == 0) { - hb_context.code_status = HAWKBIT_NO_UPDATE; - goto cleanup; + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_PROBE]); +} + +/* + * Feedback channel for the config data action + * PUT: /default/controller/v1/{controllerId}/configData + */ +static void s_config_device(void *o) +{ + int ret = 0; + struct s_object *s = (struct s_object *)o; + struct hawkbit_cfg cfg = { + .mode = "merge", + .data.VIN = s->device_id, + }; + uint8_t status_buffer[STATUS_BUFFER_SIZE] = {0}; + uint8_t url_buffer[URL_BUFFER_SIZE] = {0}; + + snprintk(url_buffer, sizeof(url_buffer), "%s/%s-%s/%s", HAWKBIT_JSON_URL, CONFIG_BOARD, + s->device_id, "configData"); + + ret = json_obj_encode_buf(json_cfg_descr, ARRAY_SIZE(json_cfg_descr), &cfg, status_buffer, + sizeof(status_buffer)); + if (ret) { + LOG_ERR("Can't encode the JSON script (%s): %d", "HAWKBIT_CONFIG_DEVICE", ret); + s->hb_context.code_status = HAWKBIT_METADATA_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; + } + + if (!send_request(&s->hb_context, HAWKBIT_CONFIG_DEVICE, url_buffer, status_buffer)) { + LOG_ERR("Send request failed (%s)", "HAWKBIT_CONFIG_DEVICE"); + smf_set_state(SMF_CTX(s), NULL); + return; + } + + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_PROBE]); +} + +/* + * Resource for software module (Deployment Base) + * GET: /default/controller/v1/{controllerId}/deploymentBase/{actionId} + */ +static void s_probe_deployment_base(void *o) +{ + int ret = 0; + int32_t action_id; + struct s_object *s = (struct s_object *)o; + char deployment_base[DEPLOYMENT_BASE_SIZE] = {0}; + uint8_t url_buffer[URL_BUFFER_SIZE] = {0}; + + ret = hawkbit_find_deployment_base(&s->hb_context.results.base, deployment_base); + if (ret < 0) { + LOG_ERR("Unable to find URL for the device's deploymentBase: %d", ret); + s->hb_context.code_status = HAWKBIT_METADATA_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; } - memset(hb_context.url_buffer, 0, sizeof(hb_context.url_buffer)); - hb_context.dl.http_content_size = 0; - hb_context.dl.downloaded_size = 0; - snprintk(hb_context.url_buffer, sizeof(hb_context.url_buffer), "%s/%s-%s/%s", - HAWKBIT_JSON_URL, CONFIG_BOARD, device_id, deployment_base); - memset(&hawkbit_results.dep, 0, sizeof(hawkbit_results.dep)); - memset(hb_context.response_data, 0, RESPONSE_BUFFER_SIZE); + snprintk(url_buffer, sizeof(url_buffer), "%s/%s-%s/%s", HAWKBIT_JSON_URL, CONFIG_BOARD, + s->device_id, deployment_base); - if (!send_request(HTTP_GET, HAWKBIT_PROBE_DEPLOYMENT_BASE, HAWKBIT_STATUS_FINISHED_NONE, - HAWKBIT_STATUS_EXEC_NONE)) { + if (!send_request(&s->hb_context, HAWKBIT_PROBE_DEPLOYMENT_BASE, url_buffer, NULL)) { LOG_ERR("Send request failed (%s)", "HAWKBIT_PROBE_DEPLOYMENT_BASE"); - hb_context.code_status = HAWKBIT_NETWORKING_ERROR; - goto cleanup; + smf_set_state(SMF_CTX(s), NULL); + return; } - if (hb_context.code_status == HAWKBIT_METADATA_ERROR) { - goto cleanup; + if (s->hb_context.code_status == HAWKBIT_METADATA_ERROR) { + smf_set_state(SMF_CTX(s), NULL); + return; } - hawkbit_dump_deployment(&hawkbit_results.dep); + hawkbit_dump_deployment(&s->hb_context.results.dep); - hb_context.dl.http_content_size = 0; - ret = hawkbit_parse_deployment(&hawkbit_results.dep, &hb_context.json_action_id, - download_http, &file_size); + ret = hawkbit_deployment_get_action_id(&s->hb_context.results.dep, + &s->hb_context.json_action_id); if (ret < 0) { - LOG_ERR("Failed to parse deploymentBase: %d", ret); - goto cleanup; + s->hb_context.code_status = HAWKBIT_METADATA_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; } nvs_read(&fs, ADDRESS_ID, &action_id, sizeof(action_id)); - if (action_id == (int32_t)hb_context.json_action_id) { - LOG_INF("Preventing repeated attempt to install %d", hb_context.json_action_id); - hb_context.dl.http_content_size = 0; - memset(hb_context.url_buffer, 0, sizeof(hb_context.url_buffer)); - snprintk(hb_context.url_buffer, sizeof(hb_context.url_buffer), - "%s/%s-%s/%s/%d/feedback", HAWKBIT_JSON_URL, CONFIG_BOARD, - device_id, "deploymentBase", hb_context.json_action_id); - - if (!send_request(HTTP_POST, HAWKBIT_REPORT, HAWKBIT_STATUS_FINISHED_SUCCESS, - HAWKBIT_STATUS_EXEC_CLOSED)) { - LOG_ERR("Send request failed (%s)", "HAWKBIT_REPORT"); - hb_context.code_status = HAWKBIT_NETWORKING_ERROR; - goto cleanup; - } - - hb_context.code_status = HAWKBIT_OK; - goto cleanup; + if (action_id == s->hb_context.json_action_id) { + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_REPORT]); + return; } LOG_INF("Ready to install update"); + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_DOWNLOAD]); + +} + +/* + * Feedback channel for the DeploymentBase action + * POST: /default/controller/v1/{controllerId}/deploymentBase/{actionId}/feedback + */ +static void s_report(void *o) +{ + int ret = 0; + struct s_object *s = (struct s_object *)o; + struct hawkbit_dep_fbk feedback = { + .status.execution = hawkbit_status_execution(HAWKBIT_STATUS_EXEC_CLOSED), + .status.result.finished = hawkbit_status_finished(HAWKBIT_STATUS_FINISHED_SUCCESS), + }; + uint8_t status_buffer[STATUS_BUFFER_SIZE] = {0}; + uint8_t url_buffer[URL_BUFFER_SIZE] = {0}; + + snprintk(url_buffer, sizeof(url_buffer), + "%s/%s-%s/%s/%d/%s", HAWKBIT_JSON_URL, CONFIG_BOARD, + s->device_id, "deploymentBase", s->hb_context.json_action_id, "feedback"); + + LOG_INF("Reporting deployment feedback %s (%s) for action %d", + feedback.status.result.finished, feedback.status.execution, + s->hb_context.json_action_id); + + ret = json_obj_encode_buf(json_dep_fbk_descr, ARRAY_SIZE(json_dep_fbk_descr), &feedback, + status_buffer, sizeof(status_buffer)); + if (ret) { + LOG_ERR("Can't encode the JSON script (%s): %d", "HAWKBIT_REPORT", ret); + s->hb_context.code_status = HAWKBIT_METADATA_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; + } - hb_context.dl.http_content_size = 0; - memset(hb_context.url_buffer, 0, sizeof(hb_context.url_buffer)); - snprintk(hb_context.url_buffer, sizeof(hb_context.url_buffer), "%s", download_http); + if (!send_request(&s->hb_context, HAWKBIT_REPORT, url_buffer, status_buffer)) { + LOG_ERR("Send request failed (%s)", "HAWKBIT_REPORT"); + smf_set_state(SMF_CTX(s), NULL); + return; + } + + smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_PROBE]); +} + +/* + * Artifact download + * GET: /default/controller/v1/{controllerId}/softwaremodules/{softwareModuleId} + * /artifacts/{fileName} + */ +static void s_download(void *o) +{ + int ret = 0; + struct s_object *s = (struct s_object *)o; + uint8_t url_buffer[DOWNLOAD_HTTP_SIZE] = {0}; + + ret = hawkbit_parse_deployment(&s->hb_context, &s->hb_context.results.dep, url_buffer, + NULL); + if (ret < 0) { + LOG_ERR("Failed to parse deploymentBase: %d", ret); + s->hb_context.code_status = HAWKBIT_METADATA_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; + } - flash_img_init(&hb_context.flash_ctx); + flash_img_init(&s->hb_context.flash_ctx); - if (!send_request(HTTP_GET, HAWKBIT_DOWNLOAD, HAWKBIT_STATUS_FINISHED_NONE, - HAWKBIT_STATUS_EXEC_NONE)) { + if (!send_request(&s->hb_context, HAWKBIT_DOWNLOAD, url_buffer, NULL)) { LOG_ERR("Send request failed (%s)", "HAWKBIT_DOWNLOAD"); - hb_context.code_status = HAWKBIT_NETWORKING_ERROR; - goto cleanup; + smf_set_state(SMF_CTX(s), NULL); + return; } - if (hb_context.code_status == HAWKBIT_DOWNLOAD_ERROR) { - goto cleanup; + if (s->hb_context.code_status == HAWKBIT_DOWNLOAD_ERROR) { + smf_set_state(SMF_CTX(s), NULL); + return; } /* Check if download finished */ - if (!hb_context.final_data_received) { + if (!s->hb_context.final_data_received) { LOG_ERR("Download incomplete"); - hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; - goto cleanup; + s->hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; } /* Verify the hash of the stored firmware */ - fic.match = hb_context.dl.file_hash; - fic.clen = hb_context.dl.downloaded_size; - if (flash_img_check(&hb_context.flash_ctx, &fic, FIXED_PARTITION_ID(SLOT1_LABEL))) { + struct flash_img_check fic = {0}; + + fic.match = s->hb_context.dl.file_hash; + fic.clen = s->hb_context.dl.downloaded_size; + if (flash_img_check(&s->hb_context.flash_ctx, &fic, FIXED_PARTITION_ID(SLOT1_LABEL))) { LOG_ERR("Failed to validate stored firmware"); - hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; - goto cleanup; + s->hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; } /* Request mcuboot to upgrade */ if (boot_request_upgrade(BOOT_UPGRADE_TEST)) { LOG_ERR("Failed to mark the image in slot 1 as pending"); - hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; - goto cleanup; + s->hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; + smf_set_state(SMF_CTX(s), NULL); + return; } /* If everything is successful */ - hb_context.code_status = HAWKBIT_UPDATE_INSTALLED; - hawkbit_device_acid_update(hb_context.json_action_id); + s->hb_context.code_status = HAWKBIT_UPDATE_INSTALLED; + hawkbit_device_acid_update(s->hb_context.json_action_id); - hb_context.dl.http_content_size = 0; + smf_set_state(SMF_CTX(s), NULL); +} -cleanup: - cleanup_connection(); +static const struct smf_state hawkbit_states[] = { + [S_HAWKBIT_START] = SMF_CREATE_STATE( + s_start, + NULL, + s_end, + NULL), + [S_HAWKBIT_HTTP] = SMF_CREATE_STATE( + s_http_start, + NULL, + s_http_end, + &hawkbit_states[S_HAWKBIT_START]), + [S_HAWKBIT_RESPONSE_DATA] = SMF_CREATE_STATE( + s_response_data_start, + NULL, + s_response_data_end, + &hawkbit_states[S_HAWKBIT_HTTP]), + [S_HAWKBIT_PROBE] = SMF_CREATE_STATE( + NULL, + s_probe, + NULL, + &hawkbit_states[S_HAWKBIT_RESPONSE_DATA]), + [S_HAWKBIT_CONFIG_DEVICE] = SMF_CREATE_STATE( + NULL, + s_config_device, + NULL, + &hawkbit_states[S_HAWKBIT_HTTP]), + [S_HAWKBIT_CLOSE] = SMF_CREATE_STATE( + NULL, + s_hawbit_close, + NULL, &hawkbit_states[S_HAWKBIT_HTTP]), + [S_HAWKBIT_PROBE_DEPLOYMENT_BASE] = SMF_CREATE_STATE( + NULL, + s_probe_deployment_base, + NULL, + &hawkbit_states[S_HAWKBIT_RESPONSE_DATA]), + [S_HAWKBIT_REPORT] = SMF_CREATE_STATE( + NULL, + s_report, + NULL, + &hawkbit_states[S_HAWKBIT_HTTP]), + [S_HAWKBIT_DOWNLOAD] = SMF_CREATE_STATE( + NULL, + s_download, + NULL, + &hawkbit_states[S_HAWKBIT_HTTP]), +}; -error: - free(hb_context.response_data); - k_sem_give(&probe_sem); - return hb_context.code_status; +enum hawkbit_response hawkbit_probe(void) +{ + int32_t ret = 0; + struct s_object s_obj = {0}; + + smf_set_initial(SMF_CTX(&s_obj), &hawkbit_states[S_HAWKBIT_PROBE]); + + while (1) { + ret = smf_run_state(SMF_CTX(&s_obj)); + if (ret != 0) { + return (enum hawkbit_response)ret; + } + } } static void autohandler(struct k_work *work) @@ -1226,6 +1337,10 @@ static void autohandler(struct k_work *work) hawkbit_reboot(); break; + case HAWKBIT_ALLOC_ERROR: + LOG_INF("Memory allocation error"); + break; + case HAWKBIT_DOWNLOAD_ERROR: LOG_INF("Update failed"); break; diff --git a/subsys/mgmt/hawkbit/hawkbit_priv.h b/subsys/mgmt/hawkbit/hawkbit_priv.h index 508d3b16f33a791..d05ae359731599a 100644 --- a/subsys/mgmt/hawkbit/hawkbit_priv.h +++ b/subsys/mgmt/hawkbit/hawkbit_priv.h @@ -42,11 +42,6 @@ enum hawkbit_status_exec { HAWKBIT_STATUS_EXEC_NONE, }; -enum hawkbit_dev_acid_t { - HAWKBIT_ACTION_ID_CURRENT = 0, - HAWKBIT_ACTION_ID_UPDATE, -}; - struct hawkbit_href { const char *href; }; @@ -139,22 +134,4 @@ struct hawkbit_dep_fbk { struct hawkbit_status status; }; -struct hawkbit_cancel { - struct hawkbit_href cancelBase; -}; - -struct entry { - char *http_req_str; - int n; -}; - -struct entry http_request[] = { - {"HAWKBIT_PROBE", 0}, - {"HAWKBIT_CONFIG_DEVICE", 1}, - {"HAWKBIT_CLOSE", 2}, - {"HAWKBIT_PROBE_DEPLOYMENT_BASE", 3}, - {"HAWKBIT_REPORT", 4}, - {"HAWKBIT_DOWNLOAD", 5}, -}; - #endif /* __HAWKBIT_PRIV_H__ */