blob: 9b476082dd8e45b8ceeab44e68a4a069a3e93525 [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/net/buf.h>
#include <zephyr/kernel.h>
#include <string.h>
#include <zephyr/mgmt/mcumgr/smp/smp_client.h>
#include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
#include <zephyr/sys/byteorder.h>
#include <mgmt/mcumgr/transport/smp_internal.h>
#include "smp_stub.h"
K_THREAD_STACK_DEFINE(smp_stub_work_queue_stack, CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_STACK_SIZE);
static mcmgr_client_data_check_fn rx_verify_cb;
static int send_client_failure;
static struct net_buf *response_buf;
static struct smp_hdr res_hdr;
static struct smp_transport smpt_test;
static struct smp_client_transport_entry smp_client_transport;
static struct k_work_q smp_work_queue;
static struct k_work stub_work;
static const struct k_work_queue_config smp_work_queue_config = {
.name = "mcumgr smp"
};
void smp_stub_set_rx_data_verify(mcmgr_client_data_check_fn cb)
{
rx_verify_cb = cb;
}
void smp_client_send_status_stub(int status)
{
send_client_failure = status;
}
struct net_buf *smp_response_buf_allocation(void)
{
smp_client_response_buf_clean();
response_buf = smp_packet_alloc();
return response_buf;
}
void smp_client_response_buf_clean(void)
{
if (response_buf) {
smp_client_buf_free(response_buf);
response_buf = NULL;
}
}
void smp_transport_read_hdr(const struct net_buf *nb, struct smp_hdr *dst_hdr)
{
memcpy(dst_hdr, nb->data, sizeof(*dst_hdr));
dst_hdr->nh_len = sys_be16_to_cpu(dst_hdr->nh_len);
dst_hdr->nh_group = sys_be16_to_cpu(dst_hdr->nh_group);
}
static uint16_t smp_uart_get_mtu(const struct net_buf *nb)
{
return 256;
}
static int smp_uart_tx_pkt(struct net_buf *nb)
{
if (send_client_failure) {
/* Test Send cmd fail */
return send_client_failure;
}
memcpy(&res_hdr, nb->data, sizeof(res_hdr));
res_hdr.nh_len = sys_be16_to_cpu(res_hdr.nh_len);
res_hdr.nh_group = sys_be16_to_cpu(res_hdr.nh_group);
res_hdr.nh_op += 1; /* Request to response */
/* Validate Input data if callback is configured */
if (rx_verify_cb) {
rx_verify_cb(nb);
}
/* Free tx buf */
net_buf_unref(nb);
if (response_buf) {
k_work_submit_to_queue(&smp_work_queue, &stub_work);
}
return 0;
}
static void smp_client_handle_reqs(struct k_work *work)
{
if (response_buf) {
smp_client_single_response(response_buf, &res_hdr);
}
}
void stub_smp_client_transport_register(void)
{
smpt_test.functions.output = smp_uart_tx_pkt;
smpt_test.functions.get_mtu = smp_uart_get_mtu;
smp_transport_init(&smpt_test);
smp_client_transport.smpt = &smpt_test;
smp_client_transport.smpt_type = SMP_SERIAL_TRANSPORT;
smp_client_transport_register(&smp_client_transport);
k_work_queue_init(&smp_work_queue);
k_work_queue_start(&smp_work_queue, smp_stub_work_queue_stack,
K_THREAD_STACK_SIZEOF(smp_stub_work_queue_stack),
CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_THREAD_PRIO, &smp_work_queue_config);
k_work_init(&stub_work, smp_client_handle_reqs);
}