/* * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOG_MODULE_REGISTER(mcumgr_grp_os_client, CONFIG_MCUMGR_GRP_OS_CLIENT_LOG_LEVEL); static struct os_mgmt_client *active_client; static K_SEM_DEFINE(mcummgr_os_client_grp_sem, 0, 1); static K_MUTEX_DEFINE(mcummgr_os_client_grp_mutex); void os_mgmt_client_init(struct os_mgmt_client *client, struct smp_client_object *smp_client) { client->smp_client = smp_client; } #ifdef CONFIG_MCUMGR_GRP_OS_CLIENT_RESET static int reset_res_fn(struct net_buf *nb, void *user_data) { if (!nb) { active_client->status = MGMT_ERR_ETIMEOUT; } else { active_client->status = MGMT_ERR_EOK; } k_sem_give(user_data); return 0; } int os_mgmt_client_reset(struct os_mgmt_client *client) { struct net_buf *nb; int rc; k_mutex_lock(&mcummgr_os_client_grp_mutex, K_FOREVER); active_client = client; /* allocate buffer */ nb = smp_client_buf_allocation(active_client->smp_client, MGMT_GROUP_ID_OS, OS_MGMT_ID_RESET, MGMT_OP_WRITE, SMP_MCUMGR_VERSION_1); if (!nb) { active_client->status = MGMT_ERR_ENOMEM; goto end; } k_sem_reset(&mcummgr_os_client_grp_sem); rc = smp_client_send_cmd(active_client->smp_client, nb, reset_res_fn, &mcummgr_os_client_grp_sem, CONFIG_SMP_CMD_DEFAULT_LIFE_TIME); if (rc) { active_client->status = rc; smp_packet_free(nb); goto end; } /* Wait for process end update event */ k_sem_take(&mcummgr_os_client_grp_sem, K_FOREVER); end: rc = active_client->status; active_client = NULL; k_mutex_unlock(&mcummgr_os_client_grp_mutex); return rc; } #endif /* CONFIG_MCUMGR_GRP_OS_CLIENT_RESET */ #ifdef CONFIG_MCUMGR_GRP_OS_CLIENT_ECHO static int echo_res_fn(struct net_buf *nb, void *user_data) { struct zcbor_string val = {0}; zcbor_state_t zsd[CONFIG_MCUMGR_SMP_CBOR_MAX_DECODING_LEVELS + 2]; size_t decoded; bool ok; int rc; struct zcbor_map_decode_key_val echo_response[] = { ZCBOR_MAP_DECODE_KEY_DECODER("r", zcbor_tstr_decode, &val) }; if (!nb) { LOG_ERR("Echo command timeout"); active_client->status = MGMT_ERR_ETIMEOUT; goto end; } /* Init ZCOR decoder state */ zcbor_new_decode_state(zsd, ARRAY_SIZE(zsd), nb->data, nb->len, 1, NULL, 0); ok = zcbor_map_decode_bulk(zsd, echo_response, ARRAY_SIZE(echo_response), &decoded) == 0; if (!ok) { active_client->status = MGMT_ERR_ECORRUPT; goto end; } active_client->status = MGMT_ERR_EOK; end: rc = active_client->status; k_sem_give(user_data); return rc; } int os_mgmt_client_echo(struct os_mgmt_client *client, const char *echo_string, size_t max_len) { struct net_buf *nb; int rc; bool ok; zcbor_state_t zse[CONFIG_MCUMGR_SMP_CBOR_MAX_DECODING_LEVELS]; k_mutex_lock(&mcummgr_os_client_grp_mutex, K_FOREVER); active_client = client; nb = smp_client_buf_allocation(active_client->smp_client, MGMT_GROUP_ID_OS, OS_MGMT_ID_ECHO, MGMT_OP_WRITE, SMP_MCUMGR_VERSION_1); if (!nb) { rc = active_client->status = MGMT_ERR_ENOMEM; goto end; } zcbor_new_encode_state(zse, ARRAY_SIZE(zse), nb->data + nb->len, net_buf_tailroom(nb), 0); ok = zcbor_map_start_encode(zse, 2) && zcbor_tstr_put_lit(zse, "d") && zcbor_tstr_put_term(zse, echo_string, max_len) && zcbor_map_end_encode(zse, 2); if (!ok) { smp_packet_free(nb); rc = active_client->status = MGMT_ERR_ENOMEM; goto end; } nb->len = zse->payload - nb->data; LOG_DBG("Echo Command packet len %d", nb->len); k_sem_reset(&mcummgr_os_client_grp_sem); rc = smp_client_send_cmd(active_client->smp_client, nb, echo_res_fn, &mcummgr_os_client_grp_sem, CONFIG_SMP_CMD_DEFAULT_LIFE_TIME); if (rc) { smp_packet_free(nb); } else { k_sem_take(&mcummgr_os_client_grp_sem, K_FOREVER); /* Take response status */ rc = active_client->status; } end: active_client = NULL; k_mutex_unlock(&mcummgr_os_client_grp_mutex); return rc; } #endif